# Veezee full docs LinkedIn, Reddit, and X (formerly Twitter) data for AI agents. No key needed to start: the first call returns data, and paying is the only human step in the product. --- ## Error reference Every tool below returns this same set of error codes. REST returns `application/problem+json`; MCP returns the same content as an error result. `message` is written as the next-turn instruction. | Code | HTTP status | Retriable | Meaning | | --- | --- | --- | --- | | `INVALID_INPUT` | 400 | no | A parameter failed validation. Check param and message for what to fix. | | `NOT_FOUND` | 404 | no | Nothing matches the given identifier or URL. | | `UNAUTHORIZED` | 401 | no | Missing, invalid, or revoked API key. | | `NOT_ENTITLED` | 403 | no | This account is not enabled for the platform you called. | | `INSUFFICIENT_CREDITS` | 402 | no | Your balance can't cover this call's quote. Check get_usage or add credits. | | `QUOTE_EXCEEDS_MAX_CREDITS` | 402 | no | The call's quote is higher than the max_credits you set. Nothing was charged. | | `IDEMPOTENCY_KEY_REQUIRED` | 400 | no | This is a metered call; send an Idempotency-Key header. | | `IDEMPOTENCY_KEY_REUSED` | 409 | no | That Idempotency-Key was already used with different arguments. Use a new key for a new call. | | `CONCURRENCY_LIMIT` | 429 | yes | Too many calls in flight for this key's plan. Wait for one to finish. | | `RATE_LIMITED` | 429 | yes | Too many calls per minute for this key's plan. Back off and retry. | | `TRIAL_CAP_EXCEEDED` | 403 | no | A trial-only limit was hit (concurrency, rate, search size, or realtime fetches). | | `BUDGET_EXHAUSTED` | 503 | no | A configured spend budget has been used up. | | `UPSTREAM_UNAVAILABLE` | 502 | yes | LinkedIn data wasn't reachable. Safe to retry. | | `PAYLOAD_TOO_LARGE` | 413 | no | The request or response exceeded the size limit. | | `INTERNAL` | 500 | yes | Something failed on our side. Safe to retry. | Errors a payment can fix add fields to this shape. INSUFFICIENT_CREDITS, TRIAL_CAP_EXCEEDED, and BUDGET_EXHAUSTED carry `upgrade_url` (give it to your human) and `offer`, its machine-readable twin; RATE_LIMITED and CONCURRENCY_LIMIT carry both on trial accounts only, where a paid plan raises the limit. `offer` holds `offer_version` (1), `reason` (the error code), `currency` ("usd"), `recommended` (which pack to lead with, currently `flex`), `packs` (pack, mode, price_usd_cents, credits or credits_per_month, and `when`, a short label for when that pack fits), `rails` (currently `stripe_checkout`), `checkout_url` (the same account-bound link as `upgrade_url`), `resume`, and `refund_policy`. Follow `offer.resume` after payment: INSUFFICIENT_CREDITS retries the same call with the SAME Idempotency-Key; TRIAL_CAP_EXCEEDED and BUDGET_EXHAUSTED retry with a fresh key; the two limit codes clear on their own with back-off, payment only raises the limit. INSUFFICIENT_CREDITS also sets `credits_required`: the credits the failed call needed. The failed attempt charged nothing. --- ## MCP call shape Every MCP tool call takes this envelope; only `name` and `arguments` change per tool: ```json { "method": "tools/call", "params": { "name": "", "arguments": { ... } } } ``` --- # Docs - Veezee Everything to call Veezee's LinkedIn, Reddit, and X tools over MCP or REST. ## Getting started ### 1. Call it, no key ``` curl "https://api.veezee.io/v1/linkedin/profiles?identifier=williamhgates" ``` No signup, no card, no key. Keyless calls run under a shared budget of 20 credits per IP per day, recent data only, no realtime, no `Idempotency-Key` needed. ### 2. Or connect over MCP, no key ``` https://mcp.veezee.io/linkedin ``` transport: streamable-http, same keyless budget as REST. ### 3. Hit the daily cap? Buy a key The error names `upgrade_url`: https://veezee.io/upgrade. Pick a pack, pay, and your API key is shown once on the confirmation page. Send it as `Authorization: Bearer ` on every REST call (plus an `Idempotency-Key` header on metered routes), or add it to your MCP client's connection headers. That checkout is the only human step in the product. Default path: use MCP when your host supports it, the SDK otherwise, REST as the fallback; the CLI and skills are conveniences layered on top of those. ## Platforms - [LinkedIn](https://veezee.io/docs/linkedin): LinkedIn leads: structured people and company data for outreach and research. - [Reddit](https://veezee.io/docs/reddit): Reddit's wedge is discussions and comment-level sentiment: what people actually say about a product, problem, or brand, straight from the comments. - [X (formerly Twitter)](https://veezee.io/docs/x): X's wedge is volume and recency: a deep chronological sweep across the whole platform, not just one community. ## Tools - **linkedin_resolve_url** (2 credits): Identify a LinkedIn URL. [/docs/tools/linkedin_resolve_url](https://veezee.io/docs/tools/linkedin_resolve_url) - **linkedin_get_profile** (4 credits): Get a LinkedIn person profile. [/docs/tools/linkedin_get_profile](https://veezee.io/docs/tools/linkedin_get_profile) - **linkedin_search_people** (10 credits): Search people on LinkedIn. [/docs/tools/linkedin_search_people](https://veezee.io/docs/tools/linkedin_search_people) - **linkedin_get_company** (4 credits): Get a LinkedIn company. [/docs/tools/linkedin_get_company](https://veezee.io/docs/tools/linkedin_get_company) - **linkedin_get_posts** (4 credits): Get recent posts by a person or company. [/docs/tools/linkedin_get_posts](https://veezee.io/docs/tools/linkedin_get_posts) - **reddit_search** (6 credits): Search Reddit posts, comments, subreddits, or users. [/docs/tools/reddit_search](https://veezee.io/docs/tools/reddit_search) - **reddit_get_subreddit** (4 credits): Get subreddit details. [/docs/tools/reddit_get_subreddit](https://veezee.io/docs/tools/reddit_get_subreddit) - **reddit_get_subreddit_posts** (4 credits): Get a subreddit's posts. [/docs/tools/reddit_get_subreddit_posts](https://veezee.io/docs/tools/reddit_get_subreddit_posts) - **reddit_get_user** (4 credits): Get a Reddit user. [/docs/tools/reddit_get_user](https://veezee.io/docs/tools/reddit_get_user) - **reddit_get_post** (4 credits): Get Reddit posts by id, with optional discussion thread. [/docs/tools/reddit_get_post](https://veezee.io/docs/tools/reddit_get_post) - **reddit_resolve_url** (2 credits): Identify a Reddit URL. [/docs/tools/reddit_resolve_url](https://veezee.io/docs/tools/reddit_resolve_url) - **x_search** (6 credits): Search X (formerly Twitter). [/docs/tools/x_search](https://veezee.io/docs/tools/x_search) - **x_get_profile** (4 credits): Get an X profile. [/docs/tools/x_get_profile](https://veezee.io/docs/tools/x_get_profile) - **x_get_tweets** (4 credits): Get an account's tweets. [/docs/tools/x_get_tweets](https://veezee.io/docs/tools/x_get_tweets) - **x_get_tweet** (4 credits): Get one tweet with full metrics. [/docs/tools/x_get_tweet](https://veezee.io/docs/tools/x_get_tweet) - **x_resolve_url** (2 credits): Identify an X URL. [/docs/tools/x_resolve_url](https://veezee.io/docs/tools/x_resolve_url) - **get_usage** (0 credits): Check credits and recent charges. [/docs/tools/get_usage](https://veezee.io/docs/tools/get_usage) ## Reference - Connect your client (verified install snippets per MCP host): https://veezee.io/docs/clients - Use cases (candidate sourcing, prospect enrichment, company research, brand monitoring, market research): https://veezee.io/use-cases/candidate-sourcing - Field reference (every field Veezee actually serves, by entity): https://veezee.io/docs/fields - Error reference (every error code, when it happens, and how to recover): https://veezee.io/docs/errors - OpenAPI (the machine-readable REST contract): https://veezee.io/openapi.json - SDK (npm install @veezee/sdk, typed TypeScript client): https://veezee.io/docs/sdk - CLI (the veezee command, every tool as a subcommand): https://veezee.io/docs/cli - Agent skills (installable SKILL.md packs for recurring jobs): https://veezee.io/docs/skills - Pricing + cost examples: https://veezee.io/pricing - AGENTS.md (non-obvious rules for agents calling Veezee): https://veezee.io/AGENTS.md --- # LinkedIn - Veezee docs LinkedIn leads: structured people and company data for outreach and research. ## Tools - **linkedin_resolve_url** (2 credits): Identify a LinkedIn URL. [/docs/tools/linkedin_resolve_url](https://veezee.io/docs/tools/linkedin_resolve_url) - **linkedin_get_profile** (4 credits): Get a LinkedIn person profile. [/docs/tools/linkedin_get_profile](https://veezee.io/docs/tools/linkedin_get_profile) - **linkedin_search_people** (10 credits): Search people on LinkedIn. [/docs/tools/linkedin_search_people](https://veezee.io/docs/tools/linkedin_search_people) - **linkedin_get_company** (4 credits): Get a LinkedIn company. [/docs/tools/linkedin_get_company](https://veezee.io/docs/tools/linkedin_get_company) - **linkedin_get_posts** (4 credits): Get recent posts by a person or company. [/docs/tools/linkedin_get_posts](https://veezee.io/docs/tools/linkedin_get_posts) `get_usage` checks balance and works the same way across every platform: free, 0 credits. https://veezee.io/docs/tools/get_usage ## Quickstart ### 1. Call it, no key ``` curl "https://api.veezee.io/v1/linkedin/profiles?identifier=williamhgates" ``` No signup, no card, no key. Keyless calls run under a shared budget of 20 credits per IP per day, recent data only, no realtime, no `Idempotency-Key` needed. ### 2. Or connect over MCP, no key ``` https://mcp.veezee.io/linkedin ``` transport: streamable-http, same keyless budget as REST. ### 3. Hit the daily cap? Buy a key The error names `upgrade_url`: https://veezee.io/upgrade. Pick a pack, pay, and your API key is shown once on the confirmation page. Send it as `Authorization: Bearer ` on every REST call (plus an `Idempotency-Key` header on metered routes), or add it to your MCP client's connection headers. That checkout is the only human step in the product. ## What comes back [url_resolution](https://veezee.io/docs/fields#url_resolution), [person](https://veezee.io/docs/fields#person), [people_search](https://veezee.io/docs/fields#people_search), [company](https://veezee.io/docs/fields#company), [posts](https://veezee.io/docs/fields#posts). Full field lists: https://veezee.io/docs/fields ## Limits - Every tool is read-only: no posting, commenting, or messaging. - No contact details: no email addresses or phone numbers. - No company search by name: linkedin_get_company takes a URL, slug, or domain; resolve a name with linkedin_search_people's current_company filter instead. - No keyword search across LinkedIn posts: linkedin_get_posts returns one entity's recent posts, not a search. Full tool reference: https://veezee.io/docs --- # Reddit - Veezee docs Reddit's wedge is discussions and comment-level sentiment: what people actually say about a product, problem, or brand, straight from the comments. ## Tools - **reddit_search** (6 credits): Search Reddit posts, comments, subreddits, or users. [/docs/tools/reddit_search](https://veezee.io/docs/tools/reddit_search) - **reddit_get_subreddit** (4 credits): Get subreddit details. [/docs/tools/reddit_get_subreddit](https://veezee.io/docs/tools/reddit_get_subreddit) - **reddit_get_subreddit_posts** (4 credits): Get a subreddit's posts. [/docs/tools/reddit_get_subreddit_posts](https://veezee.io/docs/tools/reddit_get_subreddit_posts) - **reddit_get_user** (4 credits): Get a Reddit user. [/docs/tools/reddit_get_user](https://veezee.io/docs/tools/reddit_get_user) - **reddit_get_post** (4 credits): Get Reddit posts by id, with optional discussion thread. [/docs/tools/reddit_get_post](https://veezee.io/docs/tools/reddit_get_post) - **reddit_resolve_url** (2 credits): Identify a Reddit URL. [/docs/tools/reddit_resolve_url](https://veezee.io/docs/tools/reddit_resolve_url) `get_usage` checks balance and works the same way across every platform: free, 0 credits. https://veezee.io/docs/tools/get_usage ## Quickstart ### 1. Call it, no key ``` curl "https://api.veezee.io/v1/reddit/subreddits?subreddit_name=selfhosted" ``` No signup, no card, no key. Keyless calls run under a shared budget of 20 credits per IP per day, recent data only, no realtime, no `Idempotency-Key` needed. ### 2. Or connect over MCP, no key ``` https://mcp.veezee.io/reddit ``` transport: streamable-http, same keyless budget as REST. ### 3. Hit the daily cap? Buy a key The error names `upgrade_url`: https://veezee.io/upgrade. Pick a pack, pay, and your API key is shown once on the confirmation page. Send it as `Authorization: Bearer ` on every REST call (plus an `Idempotency-Key` header on metered routes), or add it to your MCP client's connection headers. That checkout is the only human step in the product. ## What comes back [reddit_search](https://veezee.io/docs/fields#reddit_search), [subreddit](https://veezee.io/docs/fields#subreddit), [reddit_posts](https://veezee.io/docs/fields#reddit_posts), [reddit_user](https://veezee.io/docs/fields#reddit_user), [reddit_thread](https://veezee.io/docs/fields#reddit_thread), [url_resolution](https://veezee.io/docs/fields#url_resolution). Full field lists: https://veezee.io/docs/fields ## Limits - No server-side time window on comment search: filter results on created_at yourself, and poll with sort=new for monitoring. - Discover result depth caps around a few hundred results per query; decompose a broad topic into several narrower queries instead of one wide one. - Cached search results refresh on a 20-minute cycle: polling faster than that just replays the same page. Full tool reference: https://veezee.io/docs --- # X (formerly Twitter) - Veezee docs X's wedge is volume and recency: a deep chronological sweep across the whole platform, not just one community. ## Tools - **x_search** (6 credits): Search X (formerly Twitter). [/docs/tools/x_search](https://veezee.io/docs/tools/x_search) - **x_get_profile** (4 credits): Get an X profile. [/docs/tools/x_get_profile](https://veezee.io/docs/tools/x_get_profile) - **x_get_tweets** (4 credits): Get an account's tweets. [/docs/tools/x_get_tweets](https://veezee.io/docs/tools/x_get_tweets) - **x_get_tweet** (4 credits): Get one tweet with full metrics. [/docs/tools/x_get_tweet](https://veezee.io/docs/tools/x_get_tweet) - **x_resolve_url** (2 credits): Identify an X URL. [/docs/tools/x_resolve_url](https://veezee.io/docs/tools/x_resolve_url) `get_usage` checks balance and works the same way across every platform: free, 0 credits. https://veezee.io/docs/tools/get_usage ## Quickstart ### 1. Call it, no key ``` curl "https://api.veezee.io/v1/x/profiles?identifier=nasa" ``` No signup, no card, no key. Keyless calls run under a shared budget of 20 credits per IP per day, recent data only, no realtime, no `Idempotency-Key` needed. ### 2. Or connect over MCP, no key ``` https://mcp.veezee.io/x ``` transport: streamable-http, same keyless budget as REST. ### 3. Hit the daily cap? Buy a key The error names `upgrade_url`: https://veezee.io/upgrade. Pick a pack, pay, and your API key is shown once on the confirmation page. Send it as `Authorization: Bearer ` on every REST call (plus an `Idempotency-Key` header on metered routes), or add it to your MCP client's connection headers. That checkout is the only human step in the product. ## What comes back [x_search](https://veezee.io/docs/fields#x_search), [x_profile](https://veezee.io/docs/fields#x_profile), [x_tweets](https://veezee.io/docs/fields#x_tweets), [x_tweet](https://veezee.io/docs/fields#x_tweet), [url_resolution](https://veezee.io/docs/fields#url_resolution). Full field lists: https://veezee.io/docs/fields ## Limits - No batch tweet lookup: x_get_tweet fetches one tweet at a time. - t.co links cannot be resolved offline: x_resolve_url returns INVALID_INPUT for them; expand them in a browser step first. - People search returns a single page: x_search type=people has no cursor. Full tool reference: https://veezee.io/docs --- ## linkedin_resolve_url Identify what a LinkedIn URL points at before fetching it. Give any LinkedIn profile, company, or post URL (utm params, www/m subdomains, trailing slashes are fine); get back {type: person|company|post, id, handle, canonical_url}. For profile URLs, id is the stable person URN; for company URLs, id is the stable company URN; for post URLs, id is the activity URN extracted from the URL. For people, use the returned handle or id with linkedin_get_profile or linkedin_get_posts. For companies, use the returned HANDLE with linkedin_get_company or linkedin_get_posts; the company URN/id is a linkedin_search_people filter input, not a fetch identifier. Costs 2 credits. Skip this tool when you already have a slug, URN, or clean URL: linkedin_get_profile and linkedin_get_company accept those directly, so resolving first would waste 2 credits. Not for non-LinkedIn URLs; it returns INVALID_INPUT for those. Credits: 2. REST: `GET /v1/linkedin/resolve-url` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `url` | yes | `string` | A LinkedIn URL, e.g. https://www.linkedin.com/in/williamhgates or .../company/microsoft. | ### Example ```json { "url": "https://www.linkedin.com/in/williamhgates?utm_source=share" } ``` Output: returns a `url_resolution` envelope. Full field list: https://veezee.io/docs/fields#url_resolution --- ## linkedin_get_profile Fetch one person's LinkedIn profile. identifier accepts a profile URL, the slug after /in/ (e.g. 'williamhgates'), or a urn:li:fsd_profile URN; URLs are cleaned automatically. Always returns the overview (name, headline, location, current position, follower counts) plus up to 2 requested sections from about|experience|education|skills at no extra cost; each section beyond 2 adds 2 credits (max 4 sections). Costs 4 credits base. If you only have a name, use linkedin_search_people first; this tool does not search. Results from linkedin_search_people with is_anonymous=true cannot be fetched here; treat them as 'someone matching this exists' and stop. Companies belong to linkedin_get_company. Credits: 4. REST: `GET /v1/linkedin/profiles` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `identifier` | yes | `string` | Profile URL, slug (after /in/), or urn:li:fsd_profile URN. | | `sections` | no | `array` | Extra profile sections. First 2 are included in the base price. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "identifier": "williamhgates" } ``` Output: returns a `person` envelope. Full field list: https://veezee.io/docs/fields#person --- ## linkedin_search_people Find people on LinkedIn by keywords and filters. The right tool when you have a name, role, or 'who is the X at Y' question without a profile URL. Pass keywords (free text: name, title, or both) and any of first_name, last_name, title, school, current_company, past_company. If keywords is omitted it is derived from the name or title filters; school or company filters alone are rejected with INVALID_INPUT, so include keywords with those. Company filters accept a company name, slug, numeric id, or URN; names are resolved for you. Costs 10 credits including the first 10 results; each further 10 results add 1 credit (limit max 30; keyless and trial callers max 10). A cursor page is a NEW call priced the same way by its own limit, so one limit=30 call is much cheaper than three limit=10 pages; prefer a larger limit over paginating. Do NOT combine a company NAME filter with limit=30: name resolution spends one of the call's three internal fetches, so that combination is rejected. With a company name keep limit<=20; for limit=30 pass the company's numeric id or URN (linkedin_get_company returns both). Returns name, position, location, urn, public_identifier per result, a cursor for the next page, and total_matches. Results with is_anonymous=true are private profiles; do not pass them to linkedin_get_profile. For one known person with a URL/slug, call linkedin_get_profile directly instead. Credits: 10. REST: `GET /v1/linkedin/search` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `keywords` | no | `string` | Free-text query: a name, a title, or both. | | `first_name` | no | `string` | First-name filter, exact match. | | `last_name` | no | `string` | Last-name filter, exact match. | | `title` | no | `string` | Current job title filter. | | `school` | no | `string` | School or university name filter. | | `current_company` | no | `string` | Company name, slug, numeric id, or urn:li:fsd_company URN. | | `past_company` | no | `string` | Same accepted forms as current_company. | | `limit` | no | `integer` | How many results to return. | | `cursor` | no | `string` | Cursor from a previous page. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "keywords": "CTO", "current_company": "anthropic" } ``` Output: returns a `people_search` envelope. Full field list: https://veezee.io/docs/fields#people_search --- ## linkedin_get_company Fetch one company's LinkedIn page: name, description, industry, employee count, headquarters, website, founding year, specialities, and the URN/numeric id you need for linkedin_search_people company filters. identifier accepts a company URL, the slug after /company/ (e.g. 'microsoft'), or a website domain like 'microsoft.com'; numeric ids and URNs are search-filter inputs, not fetch identifiers. Domains are resolved to a company and verified against that company's website: a domain identifier always QUOTES base+4 credits (set max_credits accordingly), and the 4-credit resolution surcharge is refunded at settlement when the domain was resolved before, so known domains settle at the base price. A domain that cannot be verified to a company returns INVALID_INPUT with the closest matches instead of a guessed company. Costs 4 credits base. This tool does not search by name: if you only have an approximate company name, use linkedin_search_people's current_company filter with keywords (the filter resolves names) or give the exact slug. For the company's posts, use linkedin_get_posts with the same identifier (URL, slug, or website domain all work there too). Credits: 4. REST: `GET /v1/linkedin/companies` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `identifier` | yes | `string` | Company URL, slug (after /company/), or website domain (e.g. 'microsoft.com'). Numeric ids/URNs are not fetchable; use them only in linkedin_search_people company filters. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "identifier": "microsoft" } ``` Output: returns a `company` envelope. Full field list: https://veezee.io/docs/fields#company --- ## linkedin_get_posts Fetch the recent LinkedIn posts of one person or one company. identifier accepts a profile or company URL, a slug, a person URN, or a company website domain like 'microsoft.com'; the entity type is detected automatically. A domain resolves to its verified company first, exactly like linkedin_get_company: it QUOTES base+4 credits (set max_credits accordingly) and the surcharge is refunded at settlement for already-known domains, so they settle at the base price. Company URNs and numeric company ids are search-filter inputs, not fetch identifiers: use the company slug, URL, or domain here. Returns one page of posts (text, created_at, author, likes, comments_count, shares, is_repost, url) with a cursor for older posts. Costs 4 credits per page. Use this for 'what has X been posting', voice-of-company research, or activity checks before outreach. Not for reading one specific post you already have a URL for, and not for keyword search across LinkedIn; neither is supported in v1. Credits: 4. REST: `GET /v1/linkedin/posts` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `identifier` | yes | `string` | Person or company URL, slug, URN, or company website domain. | | `cursor` | no | `string` | Cursor from a previous page for older posts. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "identifier": "https://www.linkedin.com/company/microsoft/" } ``` Output: returns a `posts` envelope. Full field list: https://veezee.io/docs/fields#posts --- ## reddit_search Search all of Reddit by keywords. type picks the target: posts (default), comments (what people actually say about a product, problem, or brand -- unique to Reddit search), subreddits (find communities), users. Pass query as free text up to 256 characters; decompose broad topics into several narrower queries, since result depth per query is capped upstream around a few hundred results. sort applies to posts (relevance|top|new|hot|comment_count) and comments (relevance|top|new); range (past_hour..all_time) applies to posts only; both are rejected with INVALID_INPUT elsewhere. Costs 6 credits per page; a cursor page is a NEW call priced the same way. Returns one page of summaries (author, title or comment text, upvotes, comment_count, created_at, permalink, id) with a cursor; there is no server-side time window on comment search, so for monitoring filter on created_at yourself and poll with sort=new. Fetch full post bodies and discussion threads with reddit_get_post; read one community's feed with reddit_get_subreddit_posts. For high-volume recency sweeps across X instead, use x_search. Credits: 6. REST: `GET /v1/reddit/search` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `query` | yes | `string` | Free-text keywords, e.g. 'self hosted photo backup'. Not a URL; use reddit_resolve_url for URLs. | | `type` | no | `string` | What to search. 'comments' finds mentions inside discussions; 'subreddits' finds communities. | | `sort` | no | `string` | posts: any value; comments: relevance|top|new; invalid for subreddits and users. | | `range` | no | `string` | Time window. posts only. | | `cursor` | no | `string` | Cursor from a previous page. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "query": "notion alternative", "type": "comments" } ``` Output: returns a `reddit_search` envelope. Full field list: https://veezee.io/docs/fields#reddit_search --- ## reddit_get_subreddit Fetch one subreddit's profile: title, description, subscriber and active-user counts, age, NSFW flag, and topics. subreddit_name is the name without the r/ prefix, e.g. 'selfhosted'; a full reddit.com URL also works. Set include_settings to also get the community rules and moderator list for +2 credits (useful before posting or judging moderation culture). Costs 4 credits base. Subscriber counts here are the standard sizing signal for market research. This tool does not return posts: read the feed with reddit_get_subreddit_posts, and discover subreddits you don't know by name with reddit_search type=subreddits. Credits: 4. REST: `GET /v1/reddit/subreddits` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `subreddit_name` | yes | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. Full URLs are accepted and cleaned. | | `include_settings` | no | `boolean` | Also return rules and moderators for +2 credits. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "subreddit_name": "selfhosted" } ``` Output: returns a `subreddit` envelope. Full field list: https://veezee.io/docs/fields#subreddit --- ## reddit_get_subreddit_posts Fetch one page of posts from a single subreddit, the community-monitoring primitive. subreddit_name is the name without the r/ prefix. sort defaults to the subreddit's own front-page order (best); use sort=new for monitoring and top with a range for 'best of' research. Costs 4 credits per page; a cursor page is a NEW call priced the same way. Returns post summaries (title, author, upvotes, comment_count, created_at, permalink, id) with a cursor for older posts; bodies and discussions come from reddit_get_post with the returned ids. For keyword search across all of Reddit use reddit_search; this tool takes no query. Credits: 4. REST: `GET /v1/reddit/subreddit-posts` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `subreddit_name` | yes | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `sort` | no | `string` | Defaults to the subreddit's front-page order. | | `range` | no | `string` | Time window for sort=top or controversial. | | `cursor` | no | `string` | Cursor from a previous page for older posts. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "subreddit_name": "selfhosted", "sort": "new" } ``` Output: returns a `reddit_posts` envelope. Full field list: https://veezee.io/docs/fields#reddit_posts --- ## reddit_get_user Fetch one Reddit user's public profile: username, account age, karma, follower count, and description. username is the name without the u/ prefix, e.g. 'spez'; a full profile URL also works. Add up to 2 sections from comments|posts|subreddits at 2 credits each: comments and posts return that user's recent activity (first page), subreddits returns where they are active. Costs 4 credits base. Use this to profile loud voices found via reddit_search before quoting or engaging them. To find users by topic, use reddit_search type=users; this tool needs an exact username. Credits: 4. REST: `GET /v1/reddit/users` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `username` | yes | `string` | Reddit username without the u/ prefix, e.g. 'spez'. Full profile URLs are accepted and cleaned. | | `sections` | no | `array` | Extra activity sections, 2 credits each (max 2 per call). | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "username": "spez" } ``` Output: returns a `reddit_user` envelope. Full field list: https://veezee.io/docs/fields#reddit_user --- ## reddit_get_post Fetch full post content for up to 100 Reddit posts by their t3_ ids in one call -- the follow-up loop after reddit_search or reddit_get_subreddit_posts. Costs 4 credits for up to 10 ids, +1 credit per further 10 ids; every post comes back with its full body text. With exactly ONE id you may set detail to 'full' for +4 credits to also get the discussion tree (comments flattened in tree order with depth, about 200 per page, with a comments_cursor to continue), or pass comment_id (a t1_ id, also +4 credits) to fetch one specific comment in its post context. Post ids come from the other Reddit tools or from reddit_resolve_url on a post URL. Not for discovering posts; search first, then batch-fetch here. Credits: 4. REST: `GET /v1/reddit/posts` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `post_ids` | yes | `array` | 1 to 100 post ids with the t3_ prefix, e.g. ["t3_1tbups6"]. | | `detail` | no | `string` | 'full' adds the discussion tree; only valid with exactly one id, +4 credits. | | `comment_id` | no | `string` | A t1_ comment id to fetch in context; only valid with exactly one post id, +4 credits like detail 'full'. | | `sort` | no | `string` | Discussion-tree order; only with detail 'full'. | | `cursor` | no | `string` | comments_cursor from a previous detail='full' page. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "post_ids": [ "t3_1tbups6", "t3_1tbuneg" ] } ``` Output: returns a `reddit_thread` envelope. Full field list: https://veezee.io/docs/fields#reddit_thread --- ## reddit_resolve_url Identify what a Reddit URL points at before fetching it. Give any reddit.com or redd.it URL (share links, old.reddit.com, trailing params are fine); get back {type: subreddit|user|post|comment, id, handle, canonical_url}. Post URLs yield the t3_ id for reddit_get_post; comment permalinks yield the t1_ id; subreddit and user URLs yield the name for reddit_get_subreddit or reddit_get_user. Costs 2 credits and parses offline without fetching the page. Skip this tool when you already have a t3_/t1_ id, subreddit name, or username: the other Reddit tools accept those directly. Not for non-Reddit URLs; it returns INVALID_INPUT for those. Credits: 2. REST: `GET /v1/reddit/resolve-url` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `url` | yes | `string` | A Reddit URL, e.g. https://www.reddit.com/r/selfhosted/comments/1tbups6/... or https://redd.it/1tbups6. | ### Example ```json { "url": "https://redd.it/1tbups6" } ``` Output: returns a `url_resolution` envelope. Full field list: https://veezee.io/docs/fields#url_resolution --- ## x_search Search X by keywords. type picks the mode: recent (default) is the deep chronological sweep and keeps paginating as far as you follow the cursor; popular returns the highest-engagement tweets for the query; people finds accounts and returns a single page (no cursor). Advanced query operators pass through verbatim, e.g. "from:nasa", "min_faves:100", exact phrases in quotes -- there is no separate date parameter, so use since:/until: operators for time windows. Costs 6 credits per page; a cursor page is a NEW call priced the same way, so a deep sweep costs linearly in pages. Returns tweet summaries (text, author with follower count, views, likes, retweets, replies, created_at, url, id) with a cursor. Fetch one tweet's full detail with x_get_tweet and an account's timeline with x_get_tweets. For comment-level sentiment inside topic communities, reddit_search type=comments is usually the sharper instrument. Credits: 6. REST: `GET /v1/x/search` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `query` | yes | `string` | Free-text keywords; X advanced operators work, e.g. 'claude code from:AnthropicAI since:2026-06-01'. | | `type` | no | `string` | recent = chronological deep sweep; popular = top engagement; people = account search (single page). | | `cursor` | no | `string` | Cursor from a previous page. Not valid with type 'people'. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "query": "veezee api" } ``` Output: returns a `x_search` envelope. Full field list: https://veezee.io/docs/fields#x_search --- ## x_get_profile Fetch one X account's profile: name, bio, location, website, follower/following counts, tweet and media counts, verification state, and join date. identifier accepts a screen name without the @ (e.g. 'nasa'), a full x.com or twitter.com profile URL, or the numeric account id; numeric strings are treated as ids, and the rare all-digit handle can be forced with by='screen_name'. Costs 4 credits. The returned platform_fields.id is stable across handle changes; store it for repeat lookups. To find accounts by topic use x_search type=people, and to read what an account posts use x_get_tweets; this tool returns no tweets. Credits: 4. REST: `GET /v1/x/profiles` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `identifier` | yes | `string` | Screen name without the @ (e.g. 'nasa'), profile URL, or numeric account id. | | `by` | no | `string` | Force how identifier is interpreted; auto-detected when omitted. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "identifier": "nasa" } ``` Output: returns a `x_profile` envelope. Full field list: https://veezee.io/docs/fields#x_profile --- ## x_get_tweets Fetch one page of an X account's timeline. identifier is a screen name, profile URL, or numeric id (auto-detected). mode picks the view: posts (default) is the account's own tweets, posts_and_replies includes their replies, highlights is the account's pinned highlights tab. include_retweets (default true) filters retweets out when false. Costs 4 credits per page; a cursor page is a NEW call priced the same way. Returns tweet summaries with engagement counts and a cursor for older tweets. Use this for 'what has X been posting', voice checks before outreach, or drafting replies in an account's register. For keyword search across all of X use x_search; for one specific tweet you already have, x_get_tweet. Credits: 4. REST: `GET /v1/x/tweets` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `identifier` | yes | `string` | Screen name without the @, profile URL, or numeric account id. | | `mode` | no | `string` | Which timeline view to read. | | `include_retweets` | no | `boolean` | Set false to drop retweets from the page. | | `cursor` | no | `string` | Cursor from a previous page for older tweets. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "identifier": "nasa" } ``` Output: returns a `x_tweets` envelope. Full field list: https://veezee.io/docs/fields#x_tweets --- ## x_get_tweet Fetch one tweet by id with full engagement metrics: views, likes, retweets, quotes, replies, bookmarks, language, and the quoted tweet inline when there is one. tweet_id is the numeric id from a tweet URL (the digits after /status/) or from any other X tool's results; full tweet URLs are accepted too. Costs 4 credits. Use this to verify engagement before citing a tweet or to read a quoted thread hop by hop. It returns a single tweet, not the conversation around it: for the author's other tweets use x_get_tweets, and to find tweets by topic use x_search. Credits: 4. REST: `GET /v1/x/tweet` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `tweet_id` | yes | `string` | Numeric tweet id, e.g. '2054497961162478079', or a full tweet URL. | | `freshness` | no | `string` | recent (default) serves cached data from the last few hours when available; realtime forces a live fetch for +2 credits (refunded if we fall back to cached data). | | `max_credits` | no | `integer` | Spend ceiling for this one call. The call is rejected (nothing charged) if its quote exceeds this. Only the quote is ever reserved, never this ceiling. | ### Example ```json { "tweet_id": "2054497961162478079" } ``` Output: returns a `x_tweet` envelope. Full field list: https://veezee.io/docs/fields#x_tweet --- ## x_resolve_url Identify what an X (formerly Twitter) URL points at before fetching it. Give any x.com or twitter.com URL (mobile links, query params, /i/web/status forms are fine); get back {type: profile|tweet, id, handle, canonical_url}. Tweet URLs yield the numeric id for x_get_tweet; profile URLs yield the handle for x_get_profile or x_get_tweets. Costs 2 credits and parses offline without fetching the page. t.co short links cannot be expanded offline and return INVALID_INPUT telling you so; expand them in your own browser step first. Skip this tool when you already have a handle or tweet id: the other X tools accept those directly. Credits: 2. REST: `GET /v1/x/resolve-url` (auth: `required`, metered: `true`). ### Parameters | Param | Required | Type | Description | | --- | --- | --- | --- | | `url` | yes | `string` | An X URL, e.g. https://x.com/nasa/status/2054497961162478079 or https://twitter.com/nasa. | ### Example ```json { "url": "https://x.com/nasa/status/2054497961162478079" } ``` Output: returns a `url_resolution` envelope. Full field list: https://veezee.io/docs/fields#url_resolution --- ## get_usage Check your balance, plan, limits, and the last 10 charges (receipt ids included). Costs 0 credits and is exempt from the per-minute rate limit, so call it whenever you need to budget. The response includes upgrade_url (give it to your human when credits or plan limits block you; purchases credit this account directly with no login) and manage_url (give it to your human to change or cancel a paid plan in the Stripe billing portal). Trial accounts also get a claim_url that attaches an email so the account can be recovered if the key is lost. Requires an API key: keyless calls have no account, and each keyless response already reports its cost in the usage block. Not for fetching platform data. Credits: 0. REST: `GET /v1/usage` (auth: `required`, metered: `false`). ### Parameters No parameters. ### Example ```json {} ``` Output: returns a `usage` envelope. Full field list: https://veezee.io/docs/fields#usage --- # Connect your client - Veezee docs One MCP server, many hosts. Endpoint: `https://mcp.veezee.io/linkedin` (streamable-http). No key needed to start: every host below connects keyless, under a shared per-IP daily budget; buy a key at https://veezee.io/upgrade for more. Snippets verified against each client's official docs on 2026-07-11; "tested" marks what was actually exercised against production. ## Claude Code ``` claude mcp add --transport http veezee https://mcp.veezee.io/linkedin ``` Terminal; persists to ~/.claude.json (or project .mcp.json with --scope).. Status: tested end to end (real binary, 2026-07-11: linkedin_get_company at 4 credits, zero errors). Official docs: https://code.claude.com/docs/en/mcp ## claude.ai (web) ``` Settings > Connectors > Add custom connector > https://mcp.veezee.io/linkedin ``` claude.ai settings UI, no config file. Team/Enterprise: Organization settings > Connectors. Enable per-chat from the + menu. Leave the optional client id/secret fields blank.. Status: config path verified against official docs; not app-tested. Official docs: https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp ## Cursor ``` { "mcpServers": { "veezee": { "url": "https://mcp.veezee.io/linkedin" } } } ``` .cursor/mcp.json (project) or ~/.cursor/mcp.json (global). Status: config verified against official docs; desktop flow pending a human run (BLOCKERS.md). Official docs: https://cursor.com/docs/context/mcp ## Windsurf ``` { "mcpServers": { "veezee": { "serverUrl": "https://mcp.veezee.io/linkedin" } } } ``` ~/.codeium/windsurf/mcp_config.json (note the serverUrl key, not url). Status: config verified against official docs; not app-tested. Official docs: https://docs.devin.ai/desktop/cascade/mcp ## VS Code (Copilot agent mode) ``` { "servers": { "veezee": { "type": "http", "url": "https://mcp.veezee.io/linkedin" } } } ``` .vscode/mcp.json (top-level key is "servers", and "type": "http" is required). Status: config verified against official docs; not app-tested. Official docs: https://code.visualstudio.com/docs/copilot/chat/mcp-servers ## Codex CLI ``` codex mcp add veezee --url https://mcp.veezee.io/linkedin # or in ~/.codex/config.toml: [mcp_servers.veezee] url = "https://mcp.veezee.io/linkedin" ``` ~/.codex/config.toml. Status: tested end to end (real binary, headless codex exec, 2026-07-11: linkedin_get_company, error-recovery flow). Official docs: https://developers.openai.com/codex/mcp ## Cline ``` { "mcpServers": { "veezee": { "type": "streamableHttp", "url": "https://mcp.veezee.io/linkedin" } } } ``` Cline panel > MCP Servers > Remote Servers, or cline_mcp_settings.json. Set "type": "streamableHttp" explicitly.. Status: config verified against official docs; not app-tested. Official docs: https://docs.cline.bot/mcp/configuring-mcp-servers ## Zed ``` { "context_servers": { "veezee": { "url": "https://mcp.veezee.io/linkedin" } } } ``` Zed settings.json under "context_servers", or Settings > AI > MCP Servers > Add Remote Server. Status: config verified against official docs; not app-tested. Official docs: https://zed.dev/docs/ai/mcp ## Plain REST (curl) ``` curl "https://api.veezee.io/v1/linkedin/companies?identifier=microsoft" # hit the keyless cap? buy a key at https://veezee.io/upgrade, then: curl "https://api.veezee.io/v1/linkedin/companies?identifier=microsoft" \ -H "Authorization: Bearer $VEEZEE_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` Any HTTP client. Contract: https://veezee.io/openapi.json. Metered calls need an Idempotency-Key header, even on GET (keyless calls do not).. Status: tested end to end (the e2e suite runs this against production on every deploy). Official docs: https://veezee.io/openapi.json ## SDK `npm install @veezee/sdk` (Node 20+): typed client for every tool, retries and Idempotency-Keys built in. `npm install -g @veezee/sdk` also gives the `veezee` CLI. Docs: https://veezee.io/docs/sdk and https://veezee.io/docs/cli. --- # Field reference - Veezee docs Every field Veezee serves, generated from https://veezee.io/openapi.json. Only served fields appear here; nothing upstream-only. ## url_resolution | Field | Type | Description | | --- | --- | --- | | `entity` | `"url_resolution"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.input_url` | `string` | | | `common.type` | `person | company | post | subreddit | user | comment | profile | tweet` | What the URL points at, in the platform's own vocabulary. | | `common.id` | `string | null` | | | `common.handle` | `string | null` | | | `common.canonical_url` | `string | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## person | Field | Type | Description | | --- | --- | --- | | `entity` | `"person"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.full_name` | `string` | | | `common.first_name` | `string | null` | | | `common.last_name` | `string | null` | | | `common.headline` | `string | null` | | | `common.location.name` | `string | null` | | | `common.location.country_code` | `string | null` | | | `common.about` | `string | null` | | | `common.current_position.company_name` | `string | null` | | | `common.current_position.company_handle` | `string | null` | | | `common.current_position.company_url` | `string | null` | | | `common.current_position.company_urn` | `string | null` | | | `common.current_position.start_year` | `integer | null` | | | `common.experience[].company.name` | `string | null` | | | `common.experience[].company.handle` | `string | null` | | | `common.experience[].company.url` | `string | null` | | | `common.experience[].positions[].role` | `string | null` | | | `common.experience[].positions[].location` | `string | null` | | | `common.experience[].positions[].is_current` | `boolean | null` | | | `common.experience[].positions[].start_date.month` | `integer | null` | | | `common.experience[].positions[].start_date.year` | `integer | null` | | | `common.experience[].positions[].end_date.month` | `integer | null` | | | `common.experience[].positions[].end_date.year` | `integer | null` | | | `common.education[].institution` | `string | null` | | | `common.education[].institution_url` | `string | null` | | | `common.education[].degree` | `string | null` | | | `common.education[].start_year` | `integer | null` | | | `common.education[].end_year` | `integer | null` | | | `common.skills[].name` | `string` | | | `common.skills[].endorsement_count` | `integer | null` | | | `common.followers` | `integer | null` | | | `common.connections` | `integer | null` | | | `common.is_verified` | `boolean | null` | | | `common.image_url` | `string | null` | | | `common.url` | `string` | Canonical LinkedIn profile URL. | | `platform_fields.urn` | `string` | Stable LinkedIn URN (urn:li:fsd_profile:...). Use this for repeat lookups. | | `platform_fields.public_identifier` | `string | null` | | | `platform_fields.is_influencer` | `boolean | null` | | | `platform_fields.is_creator` | `boolean | null` | | | `platform_fields.is_hiring` | `boolean | null` | | | `platform_fields.has_premium` | `boolean | null` | | | `platform_fields.open_to_messages` | `boolean | null` | | | `platform_fields.pronoun` | `string | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## people_search | Field | Type | Description | | --- | --- | --- | | `entity` | `"people_search"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.results[].name` | `string` | | | `common.results[].position` | `string | null` | | | `common.results[].location` | `string | null` | | | `common.results[].followers` | `integer | null` | | | `common.results[].is_verified` | `boolean | null` | | | `common.results[].image_url` | `string | null` | | | `common.results[].url` | `string | null` | | | `common.results[].urn` | `string` | | | `common.results[].public_identifier` | `string | null` | | | `common.results[].is_anonymous` | `boolean` | True when the profile is private: it exists but linkedin_get_profile cannot dereference it. Do not retry. | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.total_matches` | `integer | null` | | | `common.returned_count` | `integer` | | | `common.truncation_hint` | `string | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## company | Field | Type | Description | | --- | --- | --- | | `entity` | `"company"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.name` | `string` | | | `common.description` | `string | null` | | | `common.website_url` | `string | null` | | | `common.industry` | `array` | | | `common.employee_count` | `integer | null` | | | `common.employee_count_range` | `string | null` | | | `common.followers` | `integer | null` | | | `common.founded_year` | `integer | null` | | | `common.specialities` | `array` | | | `common.headquarters.name` | `string | null` | | | `common.headquarters.country_code` | `string | null` | | | `common.logo_url` | `string | null` | | | `common.url` | `string` | Canonical LinkedIn company URL. | | `platform_fields.urn` | `string` | Stable LinkedIn URN (urn:li:fsd_company:...). | | `platform_fields.linkedin_id` | `integer | null` | | | `platform_fields.public_identifier` | `string | null` | | | `platform_fields.organization_type` | `string | null` | | | `platform_fields.stock_symbol` | `string | null` | | | `platform_fields.is_verified` | `boolean | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## posts | Field | Type | Description | | --- | --- | --- | | `entity` | `"posts"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.results[].urn` | `string` | | | `common.results[].url` | `string | null` | | | `common.results[].text` | `string | null` | | | `common.results[].created_at` | `string | null` | | | `common.results[].author.name` | `string | null` | | | `common.results[].author.url` | `string | null` | | | `common.results[].author.urn` | `string | null` | | | `common.results[].likes` | `integer | null` | | | `common.results[].comments_count` | `integer | null` | | | `common.results[].shares` | `integer | null` | | | `common.results[].is_repost` | `boolean | null` | | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.returned_count` | `integer` | | | `common.author_type` | `person | company` | What kind of entity the posts belong to. | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## reddit_search | Field | Type | Description | | --- | --- | --- | | `entity` | `"reddit_search"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.type` | `posts | comments | subreddits | users` | Which result array is populated. | | `common.posts[].id` | `string` | Post id with the t3_ prefix. Pass to reddit_get_post. | | `common.posts[].title` | `string | null` | | | `common.posts[].author` | `string | null` | | | `common.posts[].subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.posts[].subreddit.subscribers` | `integer | null` | | | `common.posts[].created_at` | `string | null` | | | `common.posts[].upvotes` | `integer | null` | | | `common.posts[].upvote_ratio` | `number | null` | | | `common.posts[].comment_count` | `integer | null` | | | `common.posts[].permalink` | `string | null` | | | `common.posts[].external_url` | `string | null` | | | `common.posts[].preview_text` | `string | null` | | | `common.posts[].flair` | `string | null` | | | `common.posts[].media_type` | `string | null` | | | `common.comments[].id` | `string` | Comment id with the t1_ prefix. | | `common.comments[].author` | `string | null` | | | `common.comments[].content` | `string | null` | | | `common.comments[].created_at` | `string | null` | | | `common.comments[].upvotes` | `integer | null` | | | `common.comments[].permalink` | `string | null` | | | `common.comments[].parent_id` | `string | null` | | | `common.comments[].depth` | `integer | null` | | | `common.comments[].post.id` | `string | null` | | | `common.comments[].post.title` | `string | null` | | | `common.comments[].post.subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.comments[].post.subreddit.subscribers` | `integer | null` | | | `common.subreddits[].name` | `string` | | | `common.subreddits[].description` | `string | null` | | | `common.subreddits[].subscribers` | `integer | null` | | | `common.users[].username` | `string` | | | `common.users[].created_at` | `string | null` | | | `common.users[].karma` | `integer | null` | | | `common.users[].profile_url` | `string | null` | | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.returned_count` | `integer` | | | `common.truncation_hint` | `string | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## subreddit | Field | Type | Description | | --- | --- | --- | | `entity` | `"subreddit"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.name` | `string` | | | `common.title` | `string | null` | | | `common.description` | `string | null` | | | `common.subscribers` | `integer | null` | | | `common.active_users` | `integer | null` | | | `common.created_at` | `string | null` | | | `common.is_nsfw` | `boolean | null` | | | `common.topics` | `array` | | | `common.url` | `string` | Canonical reddit.com URL for the subreddit. | | `common.rules[].name` | `string | null` | | | `common.rules[].description` | `string | null` | | | `common.moderators` | `array | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## reddit_posts | Field | Type | Description | | --- | --- | --- | | `entity` | `"reddit_posts"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.results[].id` | `string` | Post id with the t3_ prefix. Pass to reddit_get_post. | | `common.results[].title` | `string | null` | | | `common.results[].author` | `string | null` | | | `common.results[].subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.results[].subreddit.subscribers` | `integer | null` | | | `common.results[].created_at` | `string | null` | | | `common.results[].upvotes` | `integer | null` | | | `common.results[].upvote_ratio` | `number | null` | | | `common.results[].comment_count` | `integer | null` | | | `common.results[].permalink` | `string | null` | | | `common.results[].external_url` | `string | null` | | | `common.results[].preview_text` | `string | null` | | | `common.results[].flair` | `string | null` | | | `common.results[].media_type` | `string | null` | | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.returned_count` | `integer` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## reddit_user | Field | Type | Description | | --- | --- | --- | | `entity` | `"reddit_user"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.username` | `string` | | | `common.created_at` | `string | null` | | | `common.karma` | `integer | null` | | | `common.followers` | `integer | null` | | | `common.is_verified` | `boolean | null` | | | `common.description` | `string | null` | | | `common.account_type` | `string | null` | | | `common.url` | `string` | Canonical reddit.com URL for the user. | | `common.comments[].id` | `string` | Comment id with the t1_ prefix. | | `common.comments[].author` | `string | null` | | | `common.comments[].content` | `string | null` | | | `common.comments[].created_at` | `string | null` | | | `common.comments[].upvotes` | `integer | null` | | | `common.comments[].permalink` | `string | null` | | | `common.comments[].parent_id` | `string | null` | | | `common.comments[].depth` | `integer | null` | | | `common.comments[].post.id` | `string | null` | | | `common.comments[].post.title` | `string | null` | | | `common.comments[].post.subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.comments[].post.subreddit.subscribers` | `integer | null` | | | `common.posts[].id` | `string` | Post id with the t3_ prefix. Pass to reddit_get_post. | | `common.posts[].title` | `string | null` | | | `common.posts[].author` | `string | null` | | | `common.posts[].subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.posts[].subreddit.subscribers` | `integer | null` | | | `common.posts[].created_at` | `string | null` | | | `common.posts[].upvotes` | `integer | null` | | | `common.posts[].upvote_ratio` | `number | null` | | | `common.posts[].comment_count` | `integer | null` | | | `common.posts[].permalink` | `string | null` | | | `common.posts[].external_url` | `string | null` | | | `common.posts[].preview_text` | `string | null` | | | `common.posts[].flair` | `string | null` | | | `common.posts[].media_type` | `string | null` | | | `common.subreddits[].name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.subreddits[].subscribers` | `integer | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## reddit_thread | Field | Type | Description | | --- | --- | --- | | `entity` | `"reddit_thread"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.posts[].id` | `string` | Post id with the t3_ prefix. Pass to reddit_get_post. | | `common.posts[].title` | `string | null` | | | `common.posts[].author` | `string | null` | | | `common.posts[].subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.posts[].subreddit.subscribers` | `integer | null` | | | `common.posts[].created_at` | `string | null` | | | `common.posts[].upvotes` | `integer | null` | | | `common.posts[].upvote_ratio` | `number | null` | | | `common.posts[].comment_count` | `integer | null` | | | `common.posts[].permalink` | `string | null` | | | `common.posts[].external_url` | `string | null` | | | `common.posts[].preview_text` | `string | null` | | | `common.posts[].flair` | `string | null` | | | `common.posts[].media_type` | `string | null` | | | `common.posts[].content` | `string | null` | | | `common.comments[].id` | `string` | Comment id with the t1_ prefix. | | `common.comments[].author` | `string | null` | | | `common.comments[].content` | `string | null` | | | `common.comments[].created_at` | `string | null` | | | `common.comments[].upvotes` | `integer | null` | | | `common.comments[].permalink` | `string | null` | | | `common.comments[].parent_id` | `string | null` | | | `common.comments[].depth` | `integer | null` | | | `common.comments[].post.id` | `string | null` | | | `common.comments[].post.title` | `string | null` | | | `common.comments[].post.subreddit.name` | `string` | Subreddit name without the r/ prefix, e.g. 'selfhosted'. | | `common.comments[].post.subreddit.subscribers` | `integer | null` | | | `common.comments_cursor` | `string | null` | | | `common.returned_count` | `integer` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## x_search | Field | Type | Description | | --- | --- | --- | | `entity` | `"x_search"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.type` | `recent | popular | people` | Which result array is populated. | | `common.tweets[].id` | `string` | Numeric tweet id as a string. Pass to x_get_tweet. | | `common.tweets[].text` | `string | null` | | | `common.tweets[].author.screen_name` | `string | null` | | | `common.tweets[].author.name` | `string | null` | | | `common.tweets[].author.id` | `string | null` | | | `common.tweets[].author.followers` | `integer | null` | | | `common.tweets[].author.is_verified` | `boolean | null` | | | `common.tweets[].created_at` | `string | null` | | | `common.tweets[].url` | `string | null` | | | `common.tweets[].views` | `integer | null` | | | `common.tweets[].likes` | `integer | null` | | | `common.tweets[].retweets` | `integer | null` | | | `common.tweets[].replies` | `integer | null` | | | `common.tweets[].quotes` | `integer | null` | | | `common.tweets[].bookmarks` | `integer | null` | | | `common.tweets[].lang` | `string | null` | | | `common.tweets[].is_reply` | `boolean | null` | | | `common.tweets[].is_retweet` | `boolean | null` | | | `common.tweets[].is_quote` | `boolean | null` | | | `common.tweets[].in_reply_to_screen_name` | `string | null` | | | `common.tweets[].conversation_id` | `string | null` | | | `common.tweets[].possibly_sensitive` | `boolean | null` | | | `common.people[].screen_name` | `string | null` | | | `common.people[].name` | `string | null` | | | `common.people[].id` | `string | null` | | | `common.people[].followers` | `integer | null` | | | `common.people[].is_verified` | `boolean | null` | | | `common.people[].description` | `string | null` | | | `common.people[].location` | `string | null` | | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.returned_count` | `integer` | | | `common.truncation_hint` | `string | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## x_profile | Field | Type | Description | | --- | --- | --- | | `entity` | `"x_profile"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.screen_name` | `string` | | | `common.name` | `string | null` | | | `common.description` | `string | null` | | | `common.location` | `string | null` | | | `common.website_url` | `string | null` | | | `common.created_at` | `string | null` | | | `common.followers` | `integer | null` | | | `common.following` | `integer | null` | | | `common.tweets_count` | `integer | null` | | | `common.media_count` | `integer | null` | | | `common.is_verified` | `boolean | null` | | | `common.verified_type` | `string | null` | | | `common.is_protected` | `boolean | null` | | | `common.image_url` | `string | null` | | | `common.banner_url` | `string | null` | | | `common.url` | `string` | Canonical x.com profile URL. | | `platform_fields.id` | `string` | Numeric account id as a string; stable across handle changes. Use for repeat lookups. | | `platform_fields.pinned_tweet_ids` | `array | null` | | | `platform_fields.is_business_account` | `boolean | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## x_tweets | Field | Type | Description | | --- | --- | --- | | `entity` | `"x_tweets"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.results[].id` | `string` | Numeric tweet id as a string. Pass to x_get_tweet. | | `common.results[].text` | `string | null` | | | `common.results[].author.screen_name` | `string | null` | | | `common.results[].author.name` | `string | null` | | | `common.results[].author.id` | `string | null` | | | `common.results[].author.followers` | `integer | null` | | | `common.results[].author.is_verified` | `boolean | null` | | | `common.results[].created_at` | `string | null` | | | `common.results[].url` | `string | null` | | | `common.results[].views` | `integer | null` | | | `common.results[].likes` | `integer | null` | | | `common.results[].retweets` | `integer | null` | | | `common.results[].replies` | `integer | null` | | | `common.results[].quotes` | `integer | null` | | | `common.results[].bookmarks` | `integer | null` | | | `common.results[].lang` | `string | null` | | | `common.results[].is_reply` | `boolean | null` | | | `common.results[].is_retweet` | `boolean | null` | | | `common.results[].is_quote` | `boolean | null` | | | `common.results[].in_reply_to_screen_name` | `string | null` | | | `common.results[].conversation_id` | `string | null` | | | `common.results[].possibly_sensitive` | `boolean | null` | | | `common.cursor` | `string | null` | | | `common.next_url` | `string | null` | | | `common.returned_count` | `integer` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## x_tweet | Field | Type | Description | | --- | --- | --- | | `entity` | `"x_tweet"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.id` | `string` | Numeric tweet id as a string. Pass to x_get_tweet. | | `common.text` | `string | null` | | | `common.author.screen_name` | `string | null` | | | `common.author.name` | `string | null` | | | `common.author.id` | `string | null` | | | `common.author.followers` | `integer | null` | | | `common.author.is_verified` | `boolean | null` | | | `common.created_at` | `string | null` | | | `common.url` | `string | null` | | | `common.views` | `integer | null` | | | `common.likes` | `integer | null` | | | `common.retweets` | `integer | null` | | | `common.replies` | `integer | null` | | | `common.quotes` | `integer | null` | | | `common.bookmarks` | `integer | null` | | | `common.lang` | `string | null` | | | `common.is_reply` | `boolean | null` | | | `common.is_retweet` | `boolean | null` | | | `common.is_quote` | `boolean | null` | | | `common.in_reply_to_screen_name` | `string | null` | | | `common.conversation_id` | `string | null` | | | `common.possibly_sensitive` | `boolean | null` | | | `common.quoted_tweet.id` | `string` | Numeric tweet id as a string. Pass to x_get_tweet. | | `common.quoted_tweet.text` | `string | null` | | | `common.quoted_tweet.author.screen_name` | `string | null` | | | `common.quoted_tweet.author.name` | `string | null` | | | `common.quoted_tweet.author.id` | `string | null` | | | `common.quoted_tweet.author.followers` | `integer | null` | | | `common.quoted_tweet.author.is_verified` | `boolean | null` | | | `common.quoted_tweet.created_at` | `string | null` | | | `common.quoted_tweet.url` | `string | null` | | | `common.quoted_tweet.views` | `integer | null` | | | `common.quoted_tweet.likes` | `integer | null` | | | `common.quoted_tweet.retweets` | `integer | null` | | | `common.quoted_tweet.replies` | `integer | null` | | | `common.quoted_tweet.quotes` | `integer | null` | | | `common.quoted_tweet.bookmarks` | `integer | null` | | | `common.quoted_tweet.lang` | `string | null` | | | `common.quoted_tweet.is_reply` | `boolean | null` | | | `common.quoted_tweet.is_retweet` | `boolean | null` | | | `common.quoted_tweet.is_quote` | `boolean | null` | | | `common.quoted_tweet.in_reply_to_screen_name` | `string | null` | | | `common.quoted_tweet.conversation_id` | `string | null` | | | `common.quoted_tweet.possibly_sensitive` | `boolean | null` | | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | ## usage | Field | Type | Description | | --- | --- | --- | | `entity` | `"usage"` | | | `platform` | `linkedin | reddit | x | null` | | | `canonical_url` | `string | null` | | | `data_as_of` | `string | null` | | | `schema_version` | `"2"` | | | `common.plan` | `trial | payg | flex | production` | | | `common.platforms` | `array` | Platforms this account's key may call. Grants are explicit; write to hello@veezee.io to enable more. | | `common.balance_remaining` | `integer` | | | `common.realtime_ops_used` | `integer` | | | `common.realtime_ops_limit` | `integer | null` | | | `common.concurrent_limit` | `integer` | | | `common.recent_receipts[].receipt_id` | `string` | | | `common.recent_receipts[].tool` | `string` | | | `common.recent_receipts[].credits_charged` | `integer` | | | `common.recent_receipts[].created_at` | `string` | | | `common.claim_url` | `string | null` | | | `common.upgrade_url` | `string` | Give this link to your human to add credits or upgrade; purchases credit THIS account with no login. | | `common.manage_url` | `string` | Give this link to your human to change or cancel a paid plan in the Stripe billing portal. Valid at least 24 hours; call get_usage again for a fresh one. | | `freshness.source_retrieved_at` | `string | null` | | | `freshness.served_at` | `string` | | | `freshness.cache_age_seconds` | `integer | null` | | | `freshness.served_from_cache` | `boolean` | True when these bytes were served from cache rather than fetched for this call. source_retrieved_at says how old they are. | | `freshness.freshness_requested` | `recent | realtime` | | | `freshness.freshness_served` | `recent | realtime | stale` | | | `usage.receipt_id` | `string | null` | | | `usage.credits_quoted` | `integer` | | | `usage.credits_charged` | `integer` | | | `usage.balance_remaining` | `integer | null` | | | `usage.keyless_hint` | `string` | Present on keyless calls: what budget the call drew from and how to get a key with its own balance. | --- # Pricing - Veezee No key needed to start: keyless calls run under a free budget of 20 credits per IP per day. Past that, buy a key: pay-as-you-go at $2.00 per 1,000 credits (a $20.00 minimum purchase applies), or a $99.00/mo plan with 80,000 credits included. Every tool's cost is fixed and shown on every response. ## Packs | Pack | Credits | Price | Notes | | --- | --- | --- | --- | | Keyless | 20 credits/day | $0.00 | shared per IP, no signup, no card, recent data only | | Pay-as-you-go | per 1,000 credits | $2.00 | unit rate; $20.00 minimum purchase | | Flex pack | 10,000 credits | $20.00 | prepaid, does not expire while the account is open | | Production | 80,000 credits/mo | $99.00/mo | 5 concurrent, higher rate limits (120 req/min, search up to 30 results/call) | ## How to buy Buying happens on https://veezee.io/upgrade. Pick a pack with no key at all and your new API key is shown once on the confirmation page, or, from an agent, use the personalized upgrade_url that get_usage or a payment-fixable error returns to credit an existing account. Payment runs through Stripe Checkout. ## Tool costs | Tool | Credits | Notes | | --- | --- | --- | | linkedin_resolve_url | 2 | | | linkedin_get_profile | 4 | first 2 sections included; +2/section after, up to 4 total | | linkedin_search_people | 10 | first 10 results included; +1/10 more, up to 30 (10 on trial) | | linkedin_get_company | 4 | | | linkedin_get_posts | 4 | | | reddit_search | 6 | | | reddit_get_subreddit | 4 | | | reddit_get_subreddit_posts | 4 | | | reddit_get_user | 4 | | | reddit_get_post | 4 | | | reddit_resolve_url | 2 | | | x_search | 6 | | | x_get_profile | 4 | | | x_get_tweets | 4 | | | x_get_tweet | 4 | | | x_resolve_url | 2 | | | get_usage | 0 | | Realtime freshness (`freshness: "realtime"`) adds 2 credits to any tool that accepts it; refunded automatically if the live fetch falls back to cached data. Realtime needs a key: keyless calls always serve cached (`recent`) data. ## Keyless and trial-key limits Keyless calls draw from the per-IP daily budget above; see the Keyless row. A `vz_trial_` key, issued through account recovery, carries its own caps: 500 credits, 1 concurrent call, 20 calls/minute, search capped at 10 results/call, 5 realtime fetches total. ## Example costs | Call | Credits | PAYG cost | | --- | --- | --- | | linkedin_resolve_url, one URL | 2 | $0.00 | | linkedin_get_profile, up to 2 sections | 4 | $0.01 | | linkedin_get_profile, all 4 sections | 8 | $0.02 | | linkedin_search_people, limit=10 | 10 | $0.02 | | linkedin_search_people, limit=30 | 12 | $0.02 | | linkedin_get_company, one company | 4 | $0.01 | | linkedin_get_posts, one page | 4 | $0.01 | | realtime surcharge, any tool | 2 | $0.00 | --- # Trust - Veezee What Veezee stores, how it's protected, and how to leave. ## What we store We keep request and response bodies to support idempotent replay: if you retry a call with the same `Idempotency-Key`, you get back the exact stored result instead of a second charge. Bodies are kept for up to 30 days and are size-capped. Ledger events (the record of what was charged and when) are kept indefinitely, since they're your billing record. ## Telemetry Operational telemetry uses opaque, hashed identifiers, never raw account or request data. We don't put personal information in telemetry. ## Keys API keys are shown to you exactly once, at creation. We store only a hash of the key, not the key itself. ## Authentication Veezee uses API keys only. There is no OAuth flow. ## Billing and cancellation Paid plans are self-serve through Stripe. To change or cancel: ask your agent for its manage link (the free get_usage tool returns `manage_url`), or paste your API key at https://veezee.io/manage. Either opens the Stripe billing portal for your account. Flex packs are one-time purchases; nothing recurs, so there is nothing to cancel. ## Contact hello@veezee.io --- # Changelog - Veezee ## 2026-07-13: Reddit and X Reddit and X (formerly Twitter) join LinkedIn on the same contract: `reddit_search`, `reddit_get_subreddit`, `reddit_get_subreddit_posts`, `reddit_get_user`, `reddit_get_post`, `reddit_resolve_url`, `x_search`, `x_get_profile`, `x_get_tweets`, `x_get_tweet`, `x_resolve_url`, over the same MCP and REST pattern, priced per credit, keyless-first. Per-platform docs: https://veezee.io/docs/linkedin, https://veezee.io/docs/reddit, https://veezee.io/docs/x. ## 2026-07-12: v1 launch Veezee opens with LinkedIn: six tools (`linkedin_resolve_url`, `linkedin_get_profile`, `linkedin_search_people`, `linkedin_get_company`, `linkedin_get_posts`, `get_usage`) over MCP and REST (`GET /v1/linkedin/*`), priced per credit. No key needed to start: keyless calls run under a small shared per-IP daily budget (20 credits/day). Past that, buy a key at https://veezee.io/upgrade: pay, and the key is shown once on the confirmation page. --- # SDK - Veezee docs Typed TypeScript client for the Veezee REST API. Zero runtime dependencies, built on Node 20's global `fetch`. ## Install ``` npm install @veezee/sdk ``` Node 20+ required. ## Quickstart ```ts import { VeezeeClient } from "@veezee/sdk"; const client = new VeezeeClient(); // no key needed: calls run keyless, small per-IP daily budget const profile = await client.linkedin.getProfile({ identifier: "williamhgates" }); ``` Hit the keyless cap? Buy a key at `client.checkout({ pack: "flex" })` (or [/upgrade](/upgrade) in a browser); it's shown once on the confirmation page. Already have one? `new VeezeeClient({ apiKey: process.env.VEEZEE_API_KEY })`. ## The methods LinkedIn platform methods live under `client.linkedin`: `getProfile`, `searchPeople`, `getCompany`, `getPosts`. Platform-independent account and URL methods are top-level: `resolveUrl`, `getUsage` (requires a key), `checkout` (buy a key or add credits). One method per tool, same names and envelopes as the REST contract (https://veezee.io/openapi.json). Every data response carries `usage` with the receipt id, credits charged, and balance. ## Retries and idempotency The client retries RATE_LIMITED, CONCURRENCY_LIMIT, UPSTREAM_UNAVAILABLE, INTERNAL, and network failures up to 3 attempts with backoff, honoring retry_after_seconds. Each metered call gets one Idempotency-Key reused across its own retries, so retries never double-charge. Terminal errors throw `VeezeeError` with the same code/message/param shape the API returns, including `offer` and `credits_required` on payment-fixable errors. --- # CLI - Veezee docs The `veezee` CLI ships inside @veezee/sdk: a noun-verb mirror of the REST/MCP tools, JSON output with `--json`. No API key needed to start: every command works keyless under a small free per-IP daily budget; buy a key at [/upgrade](/upgrade) when you hit the cap. ## Install ``` npm install -g @veezee/sdk ``` ## Commands ``` veezee linkedin profile get fetch a person's LinkedIn profile veezee linkedin search [flags] search people on LinkedIn veezee linkedin company get fetch a company's LinkedIn page veezee linkedin posts get fetch recent posts by a person or company veezee resolve-url identify a LinkedIn URL (person/company/post) veezee usage check credits, plan, and recent charges (requires a key) ``` ## Examples ``` veezee resolve-url https://www.linkedin.com/in/williamhgates veezee linkedin profile get williamhgates --sections experience,education veezee linkedin search --keywords "CTO" --company anthropic --limit 20 veezee linkedin company get microsoft --json veezee linkedin posts get microsoft veezee usage --key vz_live_... --json ``` ## Flags `--json` prints the raw response envelope. `--key ` sets the API key (else reads `VEEZEE_API_KEY`; omit entirely for keyless calls). `--base-url ` overrides the API base URL. `linkedin profile get` also takes `--sections a,b` and `--realtime`; `linkedin search` takes `--keywords`, `--title`, `--company`, `--limit`. Exit codes: 0 success, 1 failure, 2 usage error, 4 auth required (no key, or UNAUTHORIZED/NOT_ENTITLED from the API). --- # Candidate sourcing - Veezee Candidate sourcing finds people who match a role at a target company, then fetches full profiles for the top matches. ## Recipe 1. No key needed to start: call every step below keyless, under a shared budget of 20 credits per IP per day. Hit the cap, or need `limit: 30`? Buy a key at [/upgrade](/upgrade); it's shown once on the confirmation page. 2. `linkedin_get_company`: resolve the target company once, by URL, slug, or numeric id. Returns the company's numeric id and URN for the search filter. Cost: 4 credits. 3. `linkedin_search_people`: filter by `title` and `current_company` (the numeric id from step 2), `limit: 30`. Returns matches, each flagged `is_anonymous` if private. Cost: 12 credits. 4. `linkedin_get_profile`: for the top 10 non-anonymous results, fetch with `sections: ["experience", "education"]`. Cost: 4 credits per call, 40 credits for 10. Skip any result with `is_anonymous: true`; `linkedin_get_profile` cannot dereference a private profile. Treat the search match itself as confirmation and move on. ## Total cost 56 credits for one company lookup, one search at limit 30, and 10 profile fetches. ## Limits worth knowing - Keyless calls and trial keys cap search at 10 results per call; the `limit: 30` step needs a paid key. - Pass the company's numeric id (from linkedin_get_company) when you want `limit: 30`; a company NAME filter with limit 30 is rejected. - One search at a higher limit costs less than several at a low limit; a cursor page is priced fresh by its own limit, so paging does not save credits. - With a paid key, call `get_usage` (free, exempt from the rate limit) before a large batch to check balance; keyless calls have no account to check, but each response reports its own cost. ## Run it Full reference: [/docs](/docs). A ready-made agent setup prompt: [/agent-setup/prompt.md](/agent-setup/prompt.md). --- # Prospect enrichment - Veezee Prospect enrichment turns a list of known profile identifiers into full profile data (role, current company, experience) for people you have already identified. ## Recipe 1. Try one lead keyless first: no key needed, under a shared budget of 20 credits per IP per day. A batch of 100 leads needs more than that; buy a key at [/upgrade](/upgrade) before running the full batch. It's shown once on the confirmation page. 2. `linkedin_resolve_url` (optional): only for a dirty or ambiguous profile URL. A clean URL, slug, or URN goes straight to `linkedin_get_profile`. Cost: 2 credits. 3. `linkedin_get_profile`: one call per lead, with `sections: ["experience"]`. The first two sections are included in the base fetch; each section past two adds 2 credits, up to 4 sections total. Cost: 4 credits per lead. 4. `get_usage`: free, exempt from the rate limit, once you have a key. Check balance before a large batch instead of finding out mid-run. ## Total cost 400 credits for 100 leads at one section each, within the two included sections. ## Limits worth knowing - Realtime fetches need a key: keyless calls always serve cached (`recent`) data. On a paid key, `freshness: "realtime"` adds 2 credits per call, refunded automatically if the live fetch falls back to cached data. - Skip `linkedin_resolve_url` for identifiers you already trust; it spends 2 credits for nothing on a clean URL. - A profile flagged `is_anonymous: true` in a search result is private; `linkedin_get_profile` cannot dereference it. - Set `max_credits` on a call to cap its own spend; if the quote would exceed it, nothing is charged. --- # Company research - Veezee Company research pulls a company's profile and its recent posts, for a single lookup or a repeating watchlist check. ## Recipe 1. A single check runs keyless: no key needed, under a shared budget of 20 credits per IP per day. A recurring, scheduled watchlist needs more than that; buy a key at [/upgrade](/upgrade) first. It's shown once on the confirmation page. 2. `linkedin_get_company`: one call per company, by URL, slug, or numeric id. Returns name, size, industry, founding year, specialities, and the ids other tools use. Cost: 4 credits per company. 3. `linkedin_get_posts`: same identifier, one page per company. Returns recent posts with engagement counts. Cost: 4 credits per company; each further page is priced the same. 4. `get_usage`: free, exempt from the rate limit, once you have a key. Check balance before the next scheduled run. ## Total cost 40 credits for a 5-company check, one company fetch and one post page each. ## Limits worth knowing - A paid key draws down the same balance each scheduled run, so budget across runs, not just within one. - Realtime fetches need a key: keyless calls always serve cached (`recent`) data. On a paid key, `freshness: "realtime"` adds 2 credits to a call, refunded automatically on cached fallback. The default (`recent`) is free and usually a few hours old. - A second page of posts costs the same as the first; pull only what you need. - Set `max_credits` on a call to cap its own spend before it happens. --- # Brand monitoring - Veezee Brand monitoring finds the sentences where people compare, complain, and recommend, checks the brand's home community, and sweeps X for volume. ## Recipe 1. No key needed to start: call every step below keyless, under a shared budget of 20 credits per IP per day. Running this daily needs more than that; buy a key at [/upgrade](/upgrade) first. It's shown once on the confirmation page. 2. `reddit_search` with `type: "comments"`: run a few narrow queries for the brand name and its common nicknames or misspellings. There is no server-side time window on comment search, so filter results on `created_at` yourself. Cost: 6 credits per query page. 3. `reddit_get_subreddit_posts` with `sort: "new"`: poll the brand's home community (or its category subreddit) for new posts. Cost: 4 credits per page. 4. `x_search` with `type: "recent"`: sweep X for the same brand terms, the deep chronological mode. Cost: 6 credits per page. 5. `get_usage`: free, exempt from the rate limit, once you have a key. Check balance before a scheduled run. ## Total cost A daily sweep of 3 comment searches, 1 subreddit poll, and 1 X sweep: 28 credits/day. ## Limits worth knowing - Comment search has no time-window parameter; filter on `created_at` client-side and re-poll with `sort: "new"` for fresh mentions. - Reddit's discover depth caps around a few hundred results per query; several narrow queries beat one broad one. - Cached search results refresh on a 20-minute cycle: polling faster than that replays the same page. - X search paginates as far as you follow the cursor, so a deep sweep costs linearly in pages; budget for that before running one. ## Run it Platform docs: [/docs/reddit](/docs/reddit) and [/docs/x](/docs/x). Full reference: [/docs](/docs). --- # Market research - Veezee Market research finds the communities and accounts already talking about a space, sizes them, and profiles whoever is loudest. ## Recipe 1. No key needed to start: call every step below keyless, under a shared budget of 20 credits per IP per day. Buy a key at [/upgrade](/upgrade) once you need more; it's shown once on the confirmation page. 2. `reddit_search` with `type: "subreddits"`: find communities discussing the topic. Cost: 6 credits per page. 3. `reddit_get_subreddit`: size each candidate community by subscriber and active-user counts, the standard sizing signal. Cost: 4 credits per community. 4. `x_search` with `type: "people"`: find X accounts talking about the topic. Single page, no cursor. Cost: 6 credits. 5. `reddit_get_user` and `x_get_profile`: profile the loudest voices found above before quoting or engaging them. Cost: 4 credits per Reddit user, 4 credits per X account. ## Total cost 48 credits for one subreddit-discovery page, sizing 3 candidate communities, one X people search, and profiling 3 loud voices on each platform. ## Limits worth knowing - Reddit's discover result depth caps around a few hundred per query; decompose a broad market into several narrower queries. - `x_search` with `type: "people"` returns a single page with no cursor: it is a scan, not an exhaustive directory. - `reddit_get_user` and `x_get_profile` need an exact username or handle; use the search results' author/handle fields directly, don't guess one. ## Run it Platform docs: [/docs/reddit](/docs/reddit) and [/docs/x](/docs/x). Full reference: [/docs](/docs). --- # Agent skills - Veezee docs Skills are SKILL.md instruction packs your agent installs once and reuses: each pack teaches a recurring job (inputs, tool sequence, budget rules) on top of the six Veezee tools. ## Install From GitHub: ``` npx skills add veezeehq/veezee-skills ``` Or from the npm package, after `npm install @veezee/sdk`: ``` npx skills add ./node_modules/@veezee/sdk/skills ``` Or copy the raw SKILL.md into your project's skills directory. ## Available skills - prospect-enrich: enrich known prospects with current role, company, and experience data, with per-run credit budget rules. Source: https://github.com/veezeehq/veezee-skills/blob/main/skills/prospect-enrich/SKILL.md - candidate-sourcing: turn a role spec (title, company, school) into a ranked, enriched shortlist. Source: https://github.com/veezeehq/veezee-skills/blob/main/skills/candidate-sourcing/SKILL.md - company-enrichment: enrich a batch of companies (URLs, slugs, or website domains) with firmographics. Source: https://github.com/veezeehq/veezee-skills/blob/main/skills/company-enrichment/SKILL.md - account-research: one-account pre-outreach briefing: company facts, key people, recent posts. Source: https://github.com/veezeehq/veezee-skills/blob/main/skills/account-research/SKILL.md - post-voice-research: what a person or company posts about: topics, tone, cadence. Source: https://github.com/veezeehq/veezee-skills/blob/main/skills/post-voice-research/SKILL.md The GitHub install carries all five packs. The npm package currently ships prospect-enrich; the rest join it at the next SDK release. ## Machine index Agents can enumerate the packs at https://veezee.io/.well-known/agent-skills/index.json. Truth rule: a skill only instructs what the six shipped tools actually do; every pack is validated in CI (frontmatter shape, forbidden-vocabulary scan). --- # Evidence - Veezee Public results of the B5 tool-selection eval: does a fresh-context model pick the right Veezee tool, emit a valid first call, and read a real response envelope correctly? Machine-readable twin: [/evidence/tool-selection-eval.json](/evidence/tool-selection-eval.json). ## Method Anthropic tool-eval rubric, three axes, graded by three fresh-context subagents. Picker sees ONLY the seven tool names + descriptions and a realistic user ask, and must name the right tool with no args. First-call-success sees names + descriptions + params and must emit the exact first call (tool + JSON args), validated against the frozen zod schemas. Response-usability sees a real production response envelope and must answer the user's question from it and name its next action. No agent saw the expected answers. Models: picker Haiku (the floor host), first-call Sonnet, response-usability Sonnet. Run date: 2026-07-11. ## Scope: what this does and doesn't measure This eval measures tool-selection and first-call / response-envelope usability only: whether a model picks the right tool for a realistic ask, emits a valid first call, and can read and act on a real response envelope. It does NOT measure LinkedIn data quality, coverage, or freshness, and it does NOT measure API availability or latency. ## Picker: 13/13 | Case | Ask | Expected | Selected | Result | | --- | --- | --- | --- | --- | | P1 | Find the LinkedIn profile of the CTO of Datadog. | linkedin_search_people | linkedin_search_people | pass | | P2 | What has Anthropic been posting on LinkedIn recently? | linkedin_get_posts | linkedin_get_posts | pass | | P3 | Pull the full work history for linkedin.com/in/satyanadella. | linkedin_get_profile | linkedin_get_profile | pass | | P4 | How many employees does Stripe have on LinkedIn? | linkedin_get_company | linkedin_get_company | pass | | P5 | A user pasted this link, what is it? https://www.linkedin.com/company/openai/?utm_source=chatgpt | linkedin_resolve_url or linkedin_get_company | linkedin_resolve_url | pass | | P7 | How many credits do I have left? | get_usage | get_usage | pass | | P8 | Find software engineers at Shopify who used to work at Amazon. | linkedin_search_people | linkedin_search_people | pass | | P9 | Get the education history of williamhgates. | linkedin_get_profile | linkedin_get_profile | pass | | P10 | I only have the website vercel.com. Get their LinkedIn company info. | linkedin_get_company | linkedin_get_company | pass | | P11 | Did Bill Gates post anything about malaria this month? | linkedin_get_posts | linkedin_get_posts | pass | | P12 | Look up the profile of the person named 'Jordan Rivera' who works at Datadog. | linkedin_search_people | linkedin_search_people | pass | | P13 | Check whether my key is still valid and what plan I'm on. | get_usage | get_usage | pass | | P14 | Read this specific post for me: https://www.linkedin.com/feed/update/urn:li:activity:7123456789/ | linkedin_resolve_url or none | none | pass | ## First-call success: 7/7 valid, 6/7 optimal on the first try | Case | Ask | Tool | Args | Optimal first try | | --- | --- | --- | --- | --- | | F1 | Pull the work history for linkedin.com/in/satyanadella. | linkedin_get_profile | `{"identifier":"linkedin.com/in/satyanadella","sections":["experience"]}` | yes | | F2 | Find software engineers at Shopify who used to work at Amazon. | linkedin_search_people | `{"title":"Software Engineer","current_company":"Shopify","past_company":"Amazon"}` | yes | | F3 | I only have the website vercel.com. Get their LinkedIn company info. | linkedin_get_company | `{"identifier":"vercel"}` | yes | | F4 | What has Anthropic been posting on LinkedIn recently? | linkedin_get_posts | `{"identifier":"anthropic"}` | yes | | F5 | Get the education history of williamhgates. | linkedin_get_profile | `{"identifier":"williamhgates","sections":["education"]}` | yes | | F6 | Search up to 30 results for CTOs at Anthropic, but do not spend more than 15 credits on the call. | linkedin_search_people | `{}` | no | | F7-A5 | HISTORICAL (before website domains became first-class identifiers): linkedin_get_company identifier='microsoft.com' returned a teaching INVALID_INPUT; the agent had to produce the corrected call in one turn. | linkedin_get_company | `{"identifier":"microsoft"}` | yes | **F6 needed a description fix.** The one systematic weakness this eval found. v1 and v2 tool descriptions let the model combine a company NAME filter with limit=30, which the planner rejects (name resolution plus 3 pages exceeds the internal fetch budget): recoverable via the server error, but a first-call failure. Fixed in v3 with an imperative description rule; the server error remains the safety net for agents that ignore it. | Version | Args | Outcome | | --- | --- | --- | | v1 (no caveat) | `{"title":"CTO","current_company":"Anthropic","limit":30,"max_credits":15}` | rejected by the planner (name filter + limit=30 combination) | | v2 (polite caveat added to description) | `{"title":"CTO","current_company":"Anthropic","limit":30,"max_credits":15}` | unchanged: same rejected combination | | v3 (imperative caveat: Do NOT combine a company NAME filter with limit=30...) | `{"keywords":"CTO Anthropic","title":"CTO","limit":30,"max_credits":15}` | valid: avoided the rejected combination, quote 12 <= max_credits 15; shipped as the live description | **The teaching-error case (id F7-A5 above) is historical.** Historical; superseded 2026-07-11 when website domains became first-class identifiers: 'microsoft.com' now resolves directly with zero extra turns (see the rerun below). ## Response usability: 3/3 | Case | Ask | Envelope source | Result | | --- | --- | --- | --- | | U1 | How many employees does Microsoft have on LinkedIn, and what industry is it in? | production linkedin_get_company identifier=microsoft | pass | | U2 | How many credits do I have left and what did my last few calls cost? | production get_usage | pass | | U3 | Find CTOs at Anthropic; I will want their profiles next. | production linkedin_search_people keywords=CTO current_company=1035 limit=10 | pass | ## Website-domain identifier rerun (2026-07-11) After the linkedin_get_company change that made website domains first-class identifiers (2026-07-11), the affected picker and first-call cases were rerun. Picker: 3/3 | Ask | Selected | Result | | --- | --- | --- | | bare domain (vercel.com) | linkedin_get_company | pass | | employee-count-behind-domain (stripe.com) | linkedin_get_company | pass | | subdomain paste (news.microsoft.com) | linkedin_get_company | pass | First-call: 3/3 | Case | Ask | Tool | Args | Result | | --- | --- | --- | --- | --- | | F3-rerun | I only have the website vercel.com. Get their LinkedIn company info. | linkedin_get_company | `{"identifier":"vercel.com"}` | pass | | F3b | Get LinkedIn company info for microsoft.com with a hard 6-credit ceiling. | linkedin_get_company | `{"identifier":"microsoft.com","max_credits":6}` | pass | | F3c | (a LinkedIn URL passed as the company identifier) | linkedin_get_company | `{}` | pass | Raw per-case transcripts for this rerun were not separately archived; this section reproduces the recorded verdicts. ## 30-day availability and latency Pending. Synthetics-derived 30-day availability and p50/p95 latency have not accumulated enough data yet. This section will be filled in once that monitoring window closes; no numbers are published here in the meantime. ## Verdict Descriptions pass picker and first-call on both a small fast model (Haiku) and a mid-size model (Sonnet). The one systematic weakness found (a company NAME filter combined with limit=30 on linkedin_search_people) now has an imperative description rule plus a teaching server error. The 2026-07-11 website-domain rerun is green.