# Get balance Source: https://glasser.ai/docs/api-reference/balance/get /openapi.json get /v1/balance Check your Workspace's funds and how much is available for new Runs. This free request also confirms that your Key works. # List balance history Source: https://glasser.ai/docs/api-reference/balance/history /openapi.json get /v1/balance/history Review charges, refunds, top-ups, Grants, and adjustments, newest first. Each entry shows the amount and the balance after it. Filter by kind and use next_cursor to read the next page. # Jev API Source: https://glasser.ai/docs/api-reference/data-sources/jev Classify text, score it against a rubric, or evaluate statements with TypeSafe's Jev model. Jev evaluates text or JSON against a set of questions and returns a structured answer for each question. Questions in one request share the same `state`. | Run field | Value | | - | - | | `provider` | `typesafe` | | `endpoint` | `/v1/systemone` | Send these fields with `input` to [Create a Run](/docs/api-reference/runs/create). Use [Inspect](/docs/api-reference/endpoints/inspect) for the current input schema and Price. See [API overview](/docs/api-reference/overview) for authentication and Run handling. ## Input | Field | Description | | - | - | | `state` | The content to evaluate: text, a JSON object, or a JSON array. | | `questions` | An object containing one or more questions, each with a nonempty ID. | | `model` | Optional model name. Defaults to `jev-latest`; use `jev-1.13.0` to select that version. | Each question has a `type`, `instructions` that describe what to evaluate, and `criteria` where required: | Type | Purpose | `criteria` | | - | - | - | | `choice` | Select an option | An object with 2–255 options | | `score` | Assign a score | An ordered array with 2–10 levels | | `noul` | Evaluate a yes/no statement | Optional | Answers are returned in `output.answers`, keyed by the question IDs. See the [TypeSafe API reference](https://docs.typesafe.ai/api) for question and answer formats. ## Example This request evaluates two statements about the same support ticket: ```json wrap theme={null} { "provider": "typesafe", "endpoint": "/v1/systemone", "input": { "model": "jev-1.13.0", "state": "The customer was charged twice and asks for a refund.", "questions": { "duplicate_charge": { "type": "noul", "instructions": "The customer was charged twice." }, "refund": { "type": "noul", "instructions": "The customer asks for a refund." } } } } ``` ## Token limits Batch size depends on the content in `state` and the questions. Jev 1.13 checks both limits: | Content | Limit | | - | - | | `state` + all questions | 64k tokens | | `state` + the longest question | 32k tokens | Question content includes `instructions` and `criteria`. Token counts differ from character counts. See [TypeSafe's model limits](https://docs.typesafe.ai/models) for other model versions and current rate limits. ## Provider errors Read Jev's HTTP status from `provider_response.http_status` and its error body from `provider_response.error`. A token-limit rejection has HTTP status `400` and this body: ```json theme={null} {"detail":{"error_type":"max_tokens_exceeded"}} ``` The error does not identify which limit was exceeded. Shorten `state` or the longest question to meet the 32k limit; shorten or split the questions to meet the 64k total limit. Use a new `Idempotency-Key` for the revised request. Jev returns `429` for rate limits and `529` for temporary overload. Back off before creating a new Run. See [Run response handling](/docs/api-reference/overview#read-the-result) for status fields and retries. ## Pricing Jev charges for input tokens; output tokens are free. Each batch includes and bills `state` again. Token-limit rejections with no token usage have no Charge. Inspect the Endpoint for Glasser's current Price. The Run's `charge_usd` field contains its actual Charge. # Inspect an Endpoint Source: https://glasser.ai/docs/api-reference/endpoints/inspect /openapi.json post /v1/endpoints/inspect Get an Endpoint's schemas, current Price, and example input. Use these details to prepare a Run. Use `input_schema` to prepare your request and review the Price before running it. Save `endpoint_version` for the Run; it does not lock the Price. For sync Endpoints, set your client timeout above `timeout_ms`. # List Providers and Endpoints Source: https://glasser.ai/docs/api-reference/endpoints/list GET https://api.glasser.ai/public/catalog Browse Providers and Endpoints in one public list. Use it to choose data for your product or build a Provider picker. This request is free and requires no Key or request body. It returns the full public list in one response, without pagination. Each Endpoint in `entries` belongs to a Provider in `providers`. Match them using the `provider` field. The response is cached and does not apply your Key's Policy. It contains display prices, without input schemas or full charge rules. Use [Inspect](/docs/api-reference/endpoints/inspect) with your Key for these details, then [create a Run](/docs/api-reference/runs/create) to retrieve data. ## Response **provider\_count** `integer` *required* Number of Providers in `providers`. **endpoint\_count** `integer` *required* Number of Endpoints in `entries`. **providers** `object[]` *required* Providers in the public Data Sources list. **Provider fields** **provider** `string` *required* Provider identifier, such as `apify`. Matches `entries[].provider`. **label** `string` *required* Display name, such as `Apify`. **description** `string` *required* Short description. An empty string means no description is available. **logo** `string` *required* Logo filename used by the website, not a full URL. An empty string means no logo is available. **endpoint\_count** `integer` *required* Number of entries for this Provider. **categories** `string[]` *required* Category identifiers covered by this Provider's Endpoints. **entries** `object[]` *required* One entry per Endpoint in the public list. **Endpoint fields** **provider** `string` *required* Provider identifier. Use it together with `endpoint` to inspect or run. **provider\_label** `string` *required* Provider display name. **endpoint** `string` *required* Endpoint identifier, such as `/apify/instagram-post-scraper`. **name** `string` *required* Endpoint display name. **description** `string` *required* What the Endpoint retrieves. **category** `string` *required* Category identifier, such as `instagram`. **category\_label** `string` *required* Category display name, such as `Instagram`. **price\_usd** `string` *required* Display price in USD, as a decimal string. Read with `price_unit`; inspect for the full charge rules. **price\_unit** `string` *required* `run`, `result`, or `1M input tokens`. **price\_cap\_usd** `string` Maximum charge per Run, when included for a metered Price. ## Caching and status codes Reuse the response according to `Cache-Control`. You can send its `ETag` in an `If-None-Match` header on your next request. | Status | Meaning | | - | - | | `200` | The public list as JSON. | | `304` | The ETag matches. Reuse your saved response; this response has no body. | | `503` | No list is available. Retry later; the error code is `service_unavailable`. | The server can return the previous list while it refreshes or if a refresh fails. An entry in this list does not guarantee access under your Key's Policy. # Search runnable endpoints Source: https://glasser.ai/docs/api-reference/endpoints/search /openapi.json post /v1/endpoints/search Find Endpoints for the data you need and compare Providers and Prices. Search returns ways to retrieve data; it does not retrieve the data itself. Choose a candidate, then [Inspect it](/docs/api-reference/endpoints/inspect) before running it. If results do not fit, try different keywords; low scores or the last page do not prove a capability is unavailable. # API overview Source: https://glasser.ai/docs/api-reference/overview Connect with a Key, search and inspect Endpoints, then run a request and read its result. Use paid data from specialist Providers in your own application with one Glasser Key and balance. Each **Endpoint** is one Provider operation, such as company enrichment or keyword research. Search the Data Sources, inspect an Endpoint's inputs and Price, then run it to get the Provider's data. To understand the data flow and choose how your product will connect, start with [Integrations](/docs/integrations/overview). ## Authenticate The API base URL is `https://api.glasser.ai`. Requests to `/v1` need a Key. Create one in [Keys](https://app.glasser.ai/keys) and set it as `GLASSER_API_KEY` in your environment. Send it in the `Authorization: Bearer` header. Check your connection with this free balance request: ```bash theme={null} curl --request GET \ --url https://api.glasser.ai/v1/balance \ --header "Authorization: Bearer $GLASSER_API_KEY" ``` ## Browse Providers and Endpoints [List Providers and Endpoints](/docs/api-reference/endpoints/list) with `GET /public/catalog`. This free, public request needs no Key and returns the full list in one response: `providers` describes each Provider; `entries` lists its Endpoints and display prices. Use it to choose an Endpoint during development or build a Provider picker. The list is cached and does not apply your Key's Policy. Inspect your chosen Endpoint with your Key for its schema and current Price. ## Search, inspect, run 1. **[Search Endpoints](/docs/api-reference/endpoints/search).** Find data for your task. Use `query` for search terms, such as `company enrichment`, and include the required `use_case`, such as `Create a company profile for glasser.ai`. Results identify the Provider, Endpoint, and Endpoint version, with its Price. 2. **[Inspect the Endpoint](/docs/api-reference/endpoints/inspect).** Read its `input_schema`, sample input, and Price, including the charge rules for each outcome. Use this schema to build the Provider's input. 3. **[Run the Endpoint](/docs/api-reference/runs/create).** Send the selected `provider` and `endpoint`, with the input you built, to `POST /v1/runs`. This creates a Run and retrieves the data under that Endpoint's charge rules. Search and inspection are free. Creating a Run requires an `Idempotency-Key` header. Keep the same value when retrying the same request; use a new value for a new execution. ## Read the result A data request returns a **Run**. Read these fields before using the result: | Field | What to check | | - | - | | `status` | Is the Run finished? For a `202` response, use [Get a Run](/docs/api-reference/runs/get) to check again. | | `provider_response.http_status` | Did the Provider return data or an error? `COMPLETED` can include a Provider error. | | `provider_response.error` | The Provider's error body when its response is not successful. | | `output` | The Provider's data from a successful response. | | `charge_usd` | This Run's charge, independent of its status. | | `run_url` | Open the Run in your Workspace. | A Run can return HTTP `200` with `status: "COMPLETED"` even when the Provider rejects the request. In that case, `output` is `null`; read the Provider's status and error body from `provider_response`. Run lists contain summaries only; use [Get a Run](/docs/api-reference/runs/get) for the full error details. Retrying a completed Run with the same `Idempotency-Key` and input returns the same result without another Provider call. Use a new key for another attempt, including a request with revised input. See [How It Works](/docs/how-it-works) for Run states, pricing, and retries. ## Solutions for common tasks Solutions offer a shorter path for common requests. For example, `company_intelligence` accepts a domain, then Glasser selects an Endpoint and converts the input for its Provider. Use this when the available Glasser parameters cover your task. It uses the same Key and balance and returns an ordinary Run. See [Solutions overview](/docs/api-reference/solutions/overview) for the available capabilities, Provider selection, and charges. # Create a Run Source: https://glasser.ai/docs/api-reference/runs/create /openapi.json post /v1/runs Execute an Endpoint with the input prepared from Inspect. Glasser checks your Key’s Policy and reserves funds before creating a Run. * **200:** the Run has finished. Check its status, Provider response, and charge. * **202:** an async Run is still in progress. Use [Get a Run](/docs/api-reference/runs/get) to check its result. A finished Run can contain a Provider error. Use the same `Idempotency-Key` and execution parameters when retrying. # Get a Run Source: https://glasser.ai/docs/api-reference/runs/get /openapi.json get /v1/runs/{runId} Read a Run's current status, result, and charge. Use this to check an unfinished Run or retrieve a previous result. Check `status` and `provider_response` before using `output`. A `COMPLETED` Run can include a Provider error; a `FAILED` Run can still have a charge. # List Runs Source: https://glasser.ai/docs/api-reference/runs/list /openapi.json get /v1/runs Review your Runs, newest first. Filter by status, Provider, Endpoint, Task, or metadata. Each row is a summary. Use [Get a Run](/docs/api-reference/runs/get) for the full input, output, and Provider error details. # Stop a Run Source: https://glasser.ai/docs/api-reference/runs/stop /openapi.json post /v1/runs/{runId}/stop Request a stop for an unfinished Run. Whether it can stop depends on whether dispatch has started. * **Before dispatch:** the Run stops with no charge. An expired sync deadline instead produces `FAILED` with `TIMED_OUT`. * **After dispatch:** the Run continues; its Price determines the final charge. * **Already finished:** the request returns `409`. # Company intelligence Source: https://glasser.ai/docs/api-reference/solutions/gtm/company_intelligence /openapi.json post /v1/solutions/gtm/company_intelligence Look up a company by domain: profile, technology stack, website traffic, similar businesses, funding and news, with one normalized output across Providers. Every action returns normalized `output`. The Provider's native output is not repeated there; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). `enrich` and `traffic` expose fixed top-level fields; `tech_stack`, `competitors` and `news` expose `output.items[]`; `funding` exposes `total_funding_usd` plus `items[]`. A value the selected Provider does not report is `null`; Glasser does not fill it in. Money is always USD. Read `result_status` separately from `status`: `success`, `no_result`, `error` or `pending`. An empty but valid answer is `no_result` and keeps the action's shape: every field is `null`, or `items` is `[]`. `charge_usd` totals this response's `runs` and is null until all Runs settle. With `provider: auto`, fallback can create multiple Runs, each listed in `runs[]` with its own charge. For a pending Similarweb lookup (`traffic` via Apify, HTTP 202), follow the authenticated [result\_url](/docs/api-reference/solutions/gtm/company_intelligence/result). See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by action Every field is present on every row; a value the Provider does not report is `null`. Fields follow the [field conventions](/docs/api-reference/solutions/overview#field-conventions). | action | `output` | | - | - | | `enrich` | name, website, description, industry, employees, employee\_range\_min, employee\_range\_max, founded\_year, city, region, country, country\_code, linkedin\_url, phone, total\_funding\_usd, revenue\_usd, revenue\_range\_min\_usd, revenue\_range\_max\_usd, ownership, ticker, latest\_funding\_date | | `tech_stack` | `items[]`: name, categories\[], detection\_source, predictleads\_confidence, first\_detected\_date, last\_detected\_date | | `traffic` | monthly\_visits, organic\_traffic, paid\_traffic, organic\_keywords, paid\_keywords, organic\_traffic\_value\_usd, similarweb\_global\_rank, bounce\_rate, pages\_per\_visit, avg\_visit\_duration\_seconds | | `competitors` | `items[]`: domain, name, page\_title, position, predictleads\_similarity\_score, exa\_similarity\_score, reason | | `funding` | total\_funding\_usd, `items[]`: round\_date, round, amount\_usd, investors\[], source\_url | | `news` | `items[]`: title, url, source, published\_at, event\_date, date\_text, category, snippet | * `employees` and the revenue fields are the Provider's own estimates. `revenue_usd` is a single figure; when a Provider only gives a bucket, it is `null` and the bucket edges are in `revenue_range_min_usd` / `revenue_range_max_usd`. `employee_range_min` / `employee_range_max` work the same way. An open-ended bucket such as `10000+` has a `null` maximum. * `country` is an English display name and `country_code` an ISO 3166-1 alpha-2 code. `ownership` is one of `public`, `private`, `nonprofit`, `government`, `education`, `other`, or `null`; private is never inferred. * Scores from a Provider's own model carry its name and are `null` for the others: `predictleads_similarity_score` (0–1), `exa_similarity_score` (Exa's neural similarity), `predictleads_confidence` (0–1), `similarweb_global_rank` (1 = most visited). `position` is the 1-based order in the Provider's answer. * competitors via Exa returns web pages, not company records: `name` is `null` and the page title is in `page_title`. Rows from the company's own domain and its subdomains are left out. * `monthly_visits` is worldwide (Similarweb). `organic_traffic`, `paid_traffic` and the keyword counts are for the request `country` (default `us`). `bounce_rate` is a fraction 0–1. * Dates: `*_date` and `event_date` are `YYYY-MM-DD`, `published_at` is ISO 8601 UTC, and `date_text` is Google News display text exactly as returned. LeadMagic funding dates have month precision (day `01`). * `industry`, `categories`, `round` and `category` are labels in the answering Provider's own vocabulary and are not comparable across Providers. ```json { "action": "enrich", "provider": "apollo", "status": "COMPLETED", "result_status": "success", "output": { "name": "Stripe", "website": "http://www.stripe.com", "industry": "information technology & services", "employees": 9400, "employee_range_min": null, "employee_range_max": null, "founded_year": 2010, "city": "South San Francisco", "region": "California", "country": "United States", "country_code": "US", "linkedin_url": "http://www.linkedin.com/company/stripe", "phone": "+1 415-298-5539", "total_funding_usd": 9443867423, "revenue_usd": 6935000000, "revenue_range_min_usd": null, "revenue_range_max_usd": null, "ownership": null, "ticker": null, "latest_funding_date": "2026-03-01", "description": "Stripe, Inc. is a global financial technology company…" }, "charge_usd": "0.026", "runs": [{ "provider": "apollo", "status": "COMPLETED", "charge_usd": "0.026" }], "result_url": "/v1/solutions/gtm/company_intelligence/result?token=…" } ``` # Read a company intelligence result Source: https://glasser.ai/docs/api-reference/solutions/gtm/company_intelligence/result /openapi.json get /v1/solutions/gtm/company_intelligence/result Read normalized output, delivery status, and total charges for an existing company intelligence request. Follow the result_url returned by the call. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. HTTP 200 can still carry `result_status: pending` while an asynchronous lookup runs; keep polling until `status` is terminal. This read creates no Runs, calls no Providers and does not resume fallback. # Market data Source: https://glasser.ai/docs/api-reference/solutions/gtm/market_data /openapi.json post /v1/solutions/gtm/market_data US property values, rent estimates, property records, listings, ZIP-level market statistics and stock quotes, with one normalized output. Every action returns normalized `output`. The Provider's native output is not repeated there; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). `property_value`, `property_rent`, `market_stats` and `stock_quote` expose fixed top-level fields; `property_search`, `listings_sale` and `listings_rental` expose `output.items[]`. A value the Provider does not report is `null`. Property money is USD; a stock quote carries its `currency`. Read `result_status` separately from `status`: `success`, `no_result`, `error` or `pending`. An empty but valid answer, such as an address without an estimate, is `no_result` and keeps the action's shape: every field is `null`, or `items` is `[]`. `charge_usd` totals this response's `runs`. See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by action Property fields are `address`, `property_type`, `bedrooms`, `bathrooms`, `living_area_sqft`, `lot_size_sqft`, `year_built`, `latitude`, `longitude`. Listing fields are `listing_id`, the property fields, `status`, `listing_type`, `listed_date`, `days_on_market`, `hoa_fee_usd` (monthly HOA fee), `mls_name`, `mls_number`, `agent` and `office`. `agent` and `office` are `{name, phone, email, website}`, or `null` when the Provider reports none. | action | `output` | | - | - | | `property_value` | property fields plus estimated\_value\_usd, value\_low\_usd, value\_high\_usd, comparables\_count | | `property_rent` | property fields plus estimated\_rent\_usd (monthly), rent\_low\_usd, rent\_high\_usd, comparables\_count | | `property_search` | `items[]`: property\_id, property fields, last\_sale\_price\_usd, last\_sale\_date, owner\_names\[], owner\_type, owner\_mailing\_address, owner\_occupied | | `listings_sale` | `items[]`: listing fields plus price\_usd (asking price) | | `listings_rental` | `items[]`: listing fields plus monthly\_rent\_usd | | `market_stats` | zip, updated\_at, sale `{average_price_usd, median_price_usd, average_price_per_sqft_usd, median_price_per_sqft_usd, average_days_on_market, median_days_on_market, total_listings, new_listings}`, rental `{average_rent_usd, median_rent_usd, average_rent_per_sqft_usd, median_rent_per_sqft_usd, average_days_on_market, median_days_on_market, total_listings, new_listings}` | | `stock_quote` | symbol, name, exchange, currency, price, change, change\_percent, extended\_hours\_session, extended\_hours\_price, extended\_hours\_change, extended\_hours\_change\_percent, as\_of\_text | * `comparables_count` is the number of comparable sales or rentals behind the estimate. * `last_sale_date` and `listed_date` are `YYYY-MM-DD`; `updated_at` is ISO 8601 UTC, when RentCast last refreshed the aggregate. * The `rental` side of `market_stats`, `monthly_rent_usd` and `estimated_rent_usd` are monthly rents. * `price` is the regular-session last price in `currency`; Google Finance quotes may be delayed. `change` is the absolute move in `currency` and `change_percent` is in percent points (1.5 = 1.5%), both against the previous regular close. * `extended_hours_session` is the session label as shown (Pre-market or After hours) and is `null` during regular hours. The `extended_hours_*` values compare the extended-hours quote with the regular-session price, in the same units. * `as_of_text` is the Google Finance page timestamp exactly as shown. It is not ISO and not the time of `price`. ```json { "action": "property_value", "provider": "rentcast", "status": "COMPLETED", "result_status": "success", "output": { "address": "5500 Grand Lake Dr, San Antonio, TX 78244", "property_type": "Single Family", "bedrooms": 3, "bathrooms": 2, "living_area_sqft": 1878, "lot_size_sqft": 8843, "year_built": 1973, "latitude": 29.476011, "longitude": -98.351454, "estimated_value_usd": 235000, "value_low_usd": 203000, "value_high_usd": 266000, "comparables_count": 15 }, "charge_usd": "0.0814", "runs": [{ "provider": "rentcast", "status": "COMPLETED", "charge_usd": "0.0814" }], "result_url": "/v1/solutions/gtm/market_data/result?token=…" } ``` # Read a market data result Source: https://glasser.ai/docs/api-reference/solutions/gtm/market_data/result /openapi.json get /v1/solutions/gtm/market_data/result Read normalized output, delivery status, and total charges for an existing market data request. Follow the result_url returned by the call. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. HTTP 200 can still carry `result_status: pending`; keep polling until `status` is terminal. This read creates no Runs, calls no Providers and does not resume fallback. # People search Source: https://glasser.ai/docs/api-reference/solutions/gtm/people_search /openapi.json post /v1/solutions/gtm/people_search Find people by job title, seniority, location, or employer. You can also enrich a known person's profile or find their work email. Choose an action and supply its required fields below. Every action returns normalized `output`. The Provider's native output is not repeated there; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). `search` returns `total_matches` and `output.items[]`, one row per person. `enrich` and `find_email` return one person with the same fields at the top level. A value the selected Provider does not report is `null`; Glasser does not fill it in. Read `result_status` separately from `status`: `success`, `no_result`, `error` or `pending`. An empty but valid answer is `no_result` and keeps the action's shape: every field is `null`, or `items` is `[]`. `find_email` without an email is `no_result`. `charge_usd` totals this response's `runs` and is null until all Runs settle. With `provider: auto`, fallback can create multiple Runs, each listed in `runs[]` with its own charge. See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by action Every field is present on every row; a value the Provider does not report is `null`. Fields follow the [field conventions](/docs/api-reference/solutions/overview#field-conventions). | action | `output` | | - | - | | `search` | total\_matches, `items[]`: one person per row | | `enrich` | one person | | `find_email` | one person | A person has these fields: name, first\_name, last\_name, job\_title, seniority, department, headline, linkedin\_url, city, region, country, country\_code, email, email\_status, email\_catch\_all, email\_source, phone, company\_name, company\_domain, company\_linkedin\_url, apollo\_match\_confidence, pdl\_likelihood, hunter\_email\_score, zoominfo\_accuracy\_score. * Names, job titles and labels are as the Provider reports them. PDL names are lower case. `name` is `null` when the Provider gives only first and last name; Glasser does not join them. Apollo search masks the last name, so `last_name` is `null`. * `seniority` and `department` are labels in the answering Provider's own vocabulary (for example Apollo `founder`, PDL `cxo`, LeadMagic `C-Team`). They are not the request's `seniorities` values and are not comparable across Providers. * `email` is the address the Provider gives as the work email. PDL fills it only from `work_email`; its other addresses stay on the Run. Apollo, ZoomInfo and LeadMagic search rows have no email. * `email_status` is the Provider's own verification label (`verified`, `VERIFIED`, `valid`). Providers verify in different ways, so do not compare the labels. Read them with `email_catch_all` (the domain accepts every address, so a mailbox check cannot confirm this one) and `email_source` (Hunter: `found` on the web, or `generated` from the domain's address pattern). Hunter charges for a generated address. * `total_matches` counts the matches in the Provider's whole dataset, not only this page. It is `null` for LeadMagic, which gives only the page count. * Scores from a Provider's own model carry its name and are `null` for the others: `apollo_match_confidence` (high, medium, low, none), `pdl_likelihood` (1–10), `hunter_email_score` (0–100), `zoominfo_accuracy_score` (0–100). ```json { "action": "find_email", "provider": "hunter", "status": "COMPLETED", "result_status": "success", "output": { "name": null, "first_name": "Avery", "last_name": "Example", "job_title": null, "email": "example@stripe.com", "email_status": "valid", "email_catch_all": true, "email_source": "generated", "company_name": "Stripe", "company_domain": "stripe.com", "hunter_email_score": 80, "…": "other fields null" }, "charge_usd": "0.0245", "runs": [{ "provider": "hunter", "status": "COMPLETED", "charge_usd": "0.0245" }], "result_url": "/v1/solutions/gtm/people_search/result?token=…" } ``` ## Filters * PDL matches `job_titles` exactly as given, so "CTO" does not match "Co-founder & CTO". It matches `locations` as a substring, so "london" also matches "new london, connecticut". * ZoomInfo has no `founder`, `owner`, `partner`, `head`, `entry` or `intern` level, so with `auto` those requests skip ZoomInfo. ZoomInfo's `senior` is its whole "Non Manager" tier, which also includes junior individual contributors. * Hunter search lists only the personal addresses at `company_domain`, not role mailboxes such as info\@. Prospeo enrich returns only people it holds a verified work email for. find\_email via Apollo also accepts `linkedin_url` on its own; an Apollo match without a real email is a miss and is not charged. # Read a people search result Source: https://glasser.ai/docs/api-reference/solutions/gtm/people_search/result /openapi.json get /v1/solutions/gtm/people_search/result Read normalized output, delivery status, and total charges for an existing people search request. Follow the result_url returned by the call. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. This read creates no Runs, calls no Providers and does not resume fallback. The link carries the action and the Runs, not the names, emails or other values you searched for. # SEO research Source: https://glasser.ai/docs/api-reference/solutions/gtm/seo_research /openapi.json post /v1/solutions/gtm/seo_research Research keyword volume and difficulty, search rankings, backlinks, site audits and AI-answer visibility across several Providers with one normalized output. Choose an action and supply keywords or a domain. Every action returns normalized `output`. The Provider's native output is not repeated there; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). List actions expose `output.items[]` with fixed fields per row; overview actions expose fixed top-level fields. A value the selected Provider does not report is `null`; Glasser does not convert or fill in values. Money is always USD (`cpc_usd`, `organic_traffic_value_usd`). `volume`, `traffic` and `cpc_usd` are the answering Provider's own estimates. Compare them only within one Provider (`runs[].provider`), not across Providers. Read `result_status` separately from `status`: `success`, `no_result`, `error` or `pending`. An empty but valid answer is `no_result` and keeps the action's shape: `items` is `[]`, or every top-level field is `null`. `error` with `error.code` means the Provider output could not be delivered. `charge_usd` totals this response's `runs`, including charged empty results, and is null until all Runs settle. With `provider: auto`, fallback can create multiple Runs, each listed in `runs[]` with its own charge. For a pending crawl (`site_audit`, HTTP 202), follow the authenticated [result\_url](/docs/api-reference/solutions/gtm/seo_research/result). [Get Run](/docs/api-reference/runs/get) remains native and reports an individual charge. See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by action Every field is present on every row; a value the Provider does not report is `null`. Fields follow the [field conventions](/docs/api-reference/solutions/overview#field-conventions): money ends in `_usd`, timestamps end in `_at` (ISO 8601 UTC), and `domain` is a bare hostname without `www.` or a port. Authority scores keep each Provider's own metric and name and are never converted: `ahrefs_domain_rating` (Ahrefs Domain Rating, 0–100, may have decimals), `semrush_authority_score` (Semrush Authority Score, 0–100), `dataforseo_rank` (DataForSEO rank, 0–1000) and `serpstat_domain_rank` (Serpstat Domain Rank, 0–100). Keyword difficulty is split the same way: `semrush_keyword_difficulty`, `serpstat_keyword_difficulty`, `dataforseo_keyword_difficulty` and `ahrefs_keyword_difficulty` are each 0–100 on the Provider's own model, so the same keyword can score very differently between them. `dataforseo_onpage_score` is DataForSEO's own page score. Only the field of the Provider that answered is filled; the others are `null`. `position` is the organic position: 1 is the first organic result, and SERP features such as ads or answer boxes are not counted. | action | `output` | | - | - | | `keyword_overview` | `items[]`: keyword, volume, cpc\_usd, semrush\_keyword\_difficulty, serpstat\_keyword\_difficulty, dataforseo\_keyword\_difficulty, ahrefs\_keyword\_difficulty, intent (one row per keyword) | | `keyword_ideas` | `items[]`: same row as `keyword_overview` | | `serp` | `items[]`: position, url, domain, title, snippet (organic results only) | | `domain_overview` | organic\_keywords, organic\_traffic, organic\_traffic\_value\_usd, paid\_keywords, paid\_traffic | | `ranked_keywords` | `items[]`: keyword, position, url, volume, cpc\_usd, traffic | | `organic_competitors` | `items[]`: domain, common\_keywords, organic\_keywords (the competitor's total), organic\_traffic. The target domain and its subdomains are left out. | | `backlinks_overview` | backlinks, referring\_domains, semrush\_authority\_score, dataforseo\_rank, serpstat\_domain\_rank, dofollow\_backlinks, nofollow\_backlinks | | `backlinks` | `items[]`: source\_url, target\_url, anchor, source\_ahrefs\_domain\_rating, source\_semrush\_authority\_score, source\_dataforseo\_rank, dofollow, first\_seen\_at. One row per link from every Provider. | | `referring_domains` | `items[]`: domain, ahrefs\_domain\_rating, semrush\_authority\_score, dataforseo\_rank, backlinks, dofollow\_backlinks, first\_seen\_at | | `domain_rating` | ahrefs\_domain\_rating | | `site_audit` | dataforseo\_task\_id (input to DataForSEO's OnPage report Endpoints), crawl\_progress, crawl\_stop\_reason (DataForSEO's vocabulary), pages\_crawled, dataforseo\_onpage\_score, broken\_links, non\_indexable, duplicate\_title, duplicate\_description, duplicate\_content | | `keyword_gap` | `items[]`: keyword, volume, cpc\_usd, semrush\_keyword\_difficulty, dataforseo\_keyword\_difficulty, positions `{domain: position}` (`null` = not in the top 100), keyed by the domains you sent | | `backlink_gap` | `items[]`: domain, dataforseo\_rank, backlinks\_per\_target `{competitor domain: count}` | | `page_audit` | url, status\_code, title, description, canonical, dataforseo\_onpage\_score, internal\_links, external\_links | | `visibility_history` | `items[]`: month, organic\_keywords, organic\_traffic, organic\_traffic\_value\_usd, paid\_keywords, paid\_traffic | | `ai_citations` | `items[]`: url, platform, mentions, ai\_search\_volume, is\_target\_domain. Pages most cited in AI answers that mention the domain, from any site. | | `ai_visibility` | ahrefs\_ai\_citations, ahrefs\_ai\_cited\_pages, ahrefs\_ai\_citations\_by\_platform `{platform: citations}`, dataforseo\_ai\_mentions\_by\_platform `{platform: mentions}`, dataforseo\_ai\_search\_volume\_by\_platform `{platform: AI search volume}` | `keyword_gap` rows differ by Provider: Semrush returns keywords any of the domains ranks for (a union), while DataForSEO returns keywords the competitor ranks for and you do not. `ai_visibility` reports two different metrics: Ahrefs counts citations of the domain's pages in AI answers, DataForSEO counts LLM mentions of the domain. Each Provider fills only its own fields, and there is no cross-Provider total. Semrush `first_seen_at` carries no time zone (Semrush does not state one), so it has no `Z` suffix. ```json { "action": "ranked_keywords", "provider": "dataforseo", "status": "COMPLETED", "result_status": "success", "output": { "items": [ { "keyword": "zero interest business loan", "position": 1, "url": "https://stripe.com/resources/more/zero-interest-business-loans", "volume": 1600, "cpc_usd": 14.54, "traffic": 486.4 } ] }, "charge_usd": "0.01236", "runs": [{ "provider": "dataforseo", "status": "COMPLETED", "charge_usd": "0.01236" }], "result_url": "/v1/solutions/gtm/seo_research/result?token=…" } ``` # Read an SEO research result Source: https://glasser.ai/docs/api-reference/solutions/gtm/seo_research/result /openapi.json get /v1/solutions/gtm/seo_research/result Read normalized output, delivery status, and total charges for an existing SEO research request. Follow the result_url returned by the call. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. HTTP 200 can still carry `result_status: pending` while a crawl runs; keep polling until `status` is terminal. This read creates no Runs, calls no Providers and does not resume fallback. # Social research Source: https://glasser.ai/docs/api-reference/solutions/gtm/social_research /openapi.json post /v1/solutions/gtm/social_research Public social media data on Reddit, X, YouTube, TikTok, Instagram and LinkedIn, with one normalized output per mode shared by every platform. Every mode returns normalized `output` shared by all six platforms. The Provider's native output is not repeated there; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). A value a platform or Provider does not report is `null`. Read `result_status` separately from `status`: `success`, `no_result`, `error` or `pending`. An empty but valid answer is `no_result` and keeps the mode's shape: `items` or `profiles` is `[]`, or every field is `null`. `charge_usd` totals this response's `runs`. For a pending Apify route (HTTP 202), follow the authenticated [result\_url](/docs/api-reference/solutions/gtm/social_research/result). See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by mode Fields follow the [field conventions](/docs/api-reference/solutions/overview#field-conventions). | mode | `output` | | - | - | | `profile` | platform, handle, name, url, bio, headline, website, followers, following, posts, verified | | `search` | `items[]`: id, url, title, text, author, author\_url, published\_at, likes, comments, shares, views | | `feed` | `items[]`: the same post fields | | `post` | id, url, title, text, author, author\_url, published\_at, likes, comments, shares, views | | `find` | `profiles[]`: platform, url, handle, scrapecreators\_confidence, followers (for Reddit: matching subreddits); top-level pdl\_likelihood | * `published_at` is ISO 8601 UTC, or `null` when the Provider gives no exact time (YouTube search results). * `title` is the Reddit or YouTube title. `text` is the body only (Reddit self-text, YouTube description, the tweet, caption or post text), and is `null` when there is none. * `bio` is the free-text description (LinkedIn: the About section). `headline` is the LinkedIn job-title line. `website` is the account's own site: the LinkedIn company website or the expanded X profile link. * `likes` is Reddit's net score (can be negative), X favorites, TikTok diggs, or likes and reactions elsewhere. `shares` is X retweets, TikTok share-sheet sends, or LinkedIn reposts. `views` is X impressions, TikTok plays, or YouTube and Instagram video views. * In `find`, `platform` is the lower-case network name (`twitter` becomes `x`), and `handle` is usable as the social\_research `handle`. `scrapecreators_confidence` is ScrapeCreators' 0–1 score per profile. `pdl_likelihood` is People Data Labs' 1–10 match score for the whole person, filled only on `linkedin.find`. * LinkedIn `id` is the bare activity id, without the `urn:li:activity:` prefix. ```json { "action": "x.feed", "provider": "scrapecreators", "status": "COMPLETED", "result_status": "success", "output": { "items": [ { "id": "2110166802315804689", "url": "https://x.com/stripe/status/2110166802315804689", "title": null, "text": "You can now use Underdog…", "author": "stripe", "author_url": "https://x.com/stripe", "published_at": "2026-10-14T00:32:25Z", "likes": 55, "comments": 21, "shares": 6, "views": 8447 } ] }, "charge_usd": "0.00188", "runs": [{ "provider": "scrapecreators", "status": "COMPLETED", "charge_usd": "0.00188" }], "result_url": "/v1/solutions/gtm/social_research/result?token=…" } ``` # Read a social research result Source: https://glasser.ai/docs/api-reference/solutions/gtm/social_research/result /openapi.json get /v1/solutions/gtm/social_research/result Read normalized output, delivery status, and total charges for an existing social research request. Follow the result_url returned by the call. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. HTTP 200 can still carry `result_status: pending` while an Apify route runs; keep polling until `status` is terminal. This read creates no Runs, calls no Providers and does not resume fallback. # Web research Source: https://glasser.ai/docs/api-reference/solutions/gtm/web_research /openapi.json post /v1/solutions/gtm/web_research Search the web, news, places, and other public content, retrieve a page, or get an answer with sources. Choose an action and supply a query or URL as described below. Every action returns normalized `output`; check `result_status` for delivery. News, places, scholar, shopping, images, videos and similar expose `output.items[]` with fixed fields per row; answer exposes `output.answer` and `citations[]`. Scrape exposes `text`, `markdown`, `html`, and `raw_html`; missing formats are null. The Provider's native output is not repeated in `output`; it stays on the Run and is readable with [Get Run](/docs/api-reference/runs/get). Glasser does not convert HTML to text or judge semantic quality from wording or length. Search returns `output.results[]` and supports `time_range: day | week | month | year`. An empty but valid answer is `no_result` and keeps the action's shape: `results` or `items` is `[]`, and an empty answer is `answer: null` with `citations: []`. Scrape has no empty answer: a page that cannot be delivered is `error`, with `output: null` and the reason in `error.code`. Fetch (`scrape`) uses Serper then Firecrawl within a default 30-second request budget. HTML or explicit cache-age requests go directly to Firecrawl. X/Twitter and LinkedIn enrichment exclude Firecrawl. A named Provider never falls back. Empty or invalid output, Provider errors, timeout, or missing supported formats can trigger fallback. The delivered content comes from the final Run; content from different captures is not merged. `charge_usd` totals this response's `runs`, including charged failures and empty results, and is null until all Runs settle. The final Run's lifecycle remains in `status`; `COMPLETED` alone does not prove content delivery. For pending work, follow the authenticated [result\_url](/docs/api-reference/solutions/gtm/web_research/result) to retain normalized output and total charges. [Get Run](/docs/api-reference/runs/get) remains native and reports an individual charge. Polling creates no Runs and does not resume fallback. An intentional POST retry uses the same Idempotency-Key and execution parameters, reuses existing Runs, and starts a new request time window. See [Provider selection and charges](/docs/api-reference/solutions/overview#how-provider-selection-works). ## Output by action Every field is present on every row; a value the Provider does not report is `null`. Fields follow the [field conventions](/docs/api-reference/solutions/overview#field-conventions). | action | `output` | | - | - | | `search` | `results[]`: url, title, snippet, position, published\_at, date\_text, date (deprecated) | | `news` | `items[]`: title, url, source, published\_at, date\_text, snippet | | `places` | `items[]`: name, address, category, rating, reviews, phone, website, latitude, longitude, google\_cid | | `scholar` | `items[]`: title, url, snippet, publication, year, cited\_by, pdf\_url | | `shopping` | `items[]`: title, url (Google Shopping page), merchant\_url, google\_product\_id, price\_text, seller, rating, reviews, image\_url | | `images` | `items[]`: title, image\_url, thumbnail\_url, source\_url, source, width, height | | `videos` | `items[]`: title, url, channel, source, date\_text, duration\_text, snippet, thumbnail\_url | | `answer` | answer, `citations[]`: url, title, published\_at | | `scrape` | url, final\_url, title, text, markdown, html, raw\_html, text\_character\_limit, cached, fetched\_at, quality (deprecated) | | `similar` | `items[]`: url, title, exa\_similarity\_score, published\_at, author | * `published_at` is an ISO 8601 UTC timestamp, filled only when the Provider reports a machine timestamp (Exa `publishedDate`, SerpApi news `iso_date`). `fetched_at` is the same format. * `date_text` is Google's display text exactly as returned. It may be relative to the Run's `completed_at` ("3 hours ago") and is never parsed. * search `date` is deprecated: it holds Google's display text for Serper and SerpApi and Exa's raw `publishedDate` for Exa. Use `published_at` or `date_text`. * `snippet` is Google's short excerpt, or Exa's extracted highlight for Exa; it is never the full page text. * `price_text` and `duration_text` are display strings, not parsed; the price currency follows `country`. * `rating` is Google's 1–5 star average and `reviews` is a count. `source` is a publisher or site name. * `address` is the Provider's own text; Serper may return only the street line. * `exa_similarity_score` is Exa's own score, comparable only within one response. Similar leaves out pages from the requested URL's host. * `text_character_limit` is the character cap Glasser asked the Provider to apply (10000 for Exa); text of exactly that length may be truncated. `cached` says whether the Provider served the page from its cache. * `quality` is always `unverified` and will be removed in the next breaking revision. ```json { "action": "news", "provider": "serper", "status": "COMPLETED", "result_status": "success", "output": { "items": [ { "title": "Ripple, Stripe-owned Privy partner to bring embedded wallets to XRP Ledger", "url": "https://www.theblock.co/news/business/2026-10-13-stripe-privy-ripple-xrp-ledger-wallets-418463", "source": "The Block", "published_at": null, "date_text": "18 hours ago", "snippet": "The integration will allow developers to add XRP Ledger wallets to their apps using Privy's infrastructure." } ] }, "charge_usd": "0.0011", "runs": [{ "provider": "serper", "status": "COMPLETED", "charge_usd": "0.0011" }], "result_url": "/v1/solutions/gtm/web_research/result?token=…" } ``` # Read a web research result Source: https://glasser.ai/docs/api-reference/solutions/gtm/web_research/result /openapi.json get /v1/solutions/gtm/web_research/result Read normalized output, delivery status, and total charges for an existing Web research request. Follow the result_url returned by every web_research action. Use `result_url` unchanged on the API origin and authenticate with a Key permitted to read every Run. The response uses the same fields as the initial Solution response. HTTP 200 can still contain `result_status: pending`; continue polling until the final Run is terminal. This is a read-only request. It creates no Runs, calls no Providers, and does not resume fallback or reset the execution budget. [Get Run](/docs/api-reference/runs/get) remains the separate API for native output and an individual Run's charge. # Solutions overview Source: https://glasser.ai/docs/api-reference/solutions/overview Explore GTM's six predefined data capabilities and their supported actions. A **Solution** is a predefined set of data capabilities for a type of user. Glasser currently provides the **GTM Solution** (`gtm`) for sales and marketing research, with the six capabilities listed below. A **Capability** is one member of that Solution, such as `company_intelligence` or `people_search`. Each has a fixed set of supported actions and inputs. ## Why use a Solution? For example, **Company intelligence** can look up a company by domain. You send `domain`; Glasser selects a supported Provider, maps the input to its Endpoint, and can try another eligible Provider on supported failures. This keeps Provider-specific input formats out of your integration: you send `domain` whether the selected Provider expects `domain`, `website`, or `company_website`. Use a Solution when its inputs cover your task. If you need a specific Endpoint, its full input options, or its exact Price before execution, use [search](/docs/api-reference/endpoints/search), [inspect](/docs/api-reference/endpoints/inspect), and [run](/docs/api-reference/runs/create) to select and call it directly. ## Available capabilities Each Capability has its own request path under `/v1/solutions/gtm/`. | Capability | What you can request | | - | - | | [Web research](/docs/api-reference/solutions/gtm/web_research) | Web and news search, places, shopping results, and page content. | | [Company intelligence](/docs/api-reference/solutions/gtm/company_intelligence) | Company profiles, technology, traffic, competitors, funding, and news. | | [People search](/docs/api-reference/solutions/gtm/people_search) | Find people, enrich profiles, and look up business contact information. | | [SEO research](/docs/api-reference/solutions/gtm/seo_research) | Keyword data, rankings, backlinks, search competitors, keyword and backlink gaps, ranking history, site crawls, page checks, and AI answer citations. | | [Social research](/docs/api-reference/solutions/gtm/social_research) | Platform-specific profiles, posts, comments, and search results. | | [Market data](/docs/api-reference/solutions/gtm/market_data) | US property records, value and rent estimates, listings, and stock quotes. | The reference for each Capability lists its supported actions, Providers, and required fields. Most use `action` to select what to do; Social research uses `platform` and `mode`. > [!WARNING] > > **Breaking change in this release.** Web research, SEO research, Company intelligence, > Social research and Market data now return normalized `output` for every action. > Before, SEO research, Company intelligence, Social research and Market data returned the > Provider's native body in `output`, and Web research search and scrape carried the > Provider's native keys next to the normalized fields. Native data is no longer in > `output`: read it from the Run with `runs[].id` and [Get Run](/docs/api-reference/runs/get) > (`GET /v1/runs/:id`). Web research search keeps its `date` field (deprecated; use > `published_at` or `date_text`). > > People search now also returns normalized `output`. Before, its `output` was the answering > Provider's native body. `search` returns `total_matches` and `output.items[]` of people; > `enrich` and `find_email` return one person with the same fields. Read native data from the Run. ## Example: get a company profile Set up your Key as described in the [API overview](/docs/api-reference/overview). This request executes paid data retrieval: ```bash theme={null} curl --request POST \ --url https://api.glasser.ai/v1/solutions/gtm/company_intelligence \ --header "Authorization: Bearer $GLASSER_API_KEY" \ --header "Content-Type: application/json" \ --header "Idempotency-Key: company-profile-glasser-001" \ --data '{"domain":"glasser.ai"}' ``` For this Capability, `domain` is the only required body field. Omitting `action` uses `enrich`; omitting `provider` uses `auto`. `metadata` is optional and can be left out. Keep the same `Idempotency-Key` when retrying this request; choose a new value for a fresh lookup or a different request. ## How Provider selection works | Choice | Behavior | | - | - | | `provider: "auto"` (default) | Use the first eligible Provider in Glasser's preference order. This does not compare live prices. | | A named Provider, such as `"apollo"` | Use that Provider only, with no fallback. It must support the request and be permitted by your Key. | With `auto`, Glasser can try the next eligible Provider after a Provider error, timeout, or Endpoint unavailability. Search does not fall back on an empty result. Fetch (`scrape`) can also fall back on empty or invalid output and missing supported formats, within the request budget. Content wording and length do not trigger fallback. Each selected Endpoint must support your inputs and be allowed by your Key. ## Results and charges Every Web research action returns normalized `output`. Scrape exposes `text`, `markdown`, `html` and `raw_html`; missing formats are null. Search exposes `output.results[]`; news, places, scholar, shopping, images, videos and similar expose `output.items[]` with fixed fields per row; answer exposes `output.answer` and `citations[]`. The Provider's native output is not repeated in `output`; it stays on the Run and is readable with Get Run. Glasser does not convert HTML to text or merge captures. Read `result_status` for delivery: `success`, `partial`, `no_result`, `error` or `pending`. Missing requested formats appear in `missing_formats`. Delivery errors have `output: null` and an `error`. Content semantics remain unverified. `charge_usd` is the total for the listed `runs`, including charged failures and empty results. Each Run has its own charge and clause in `runs[]`. An unsettled Run makes the total null; multiple Runs have no single top-level `charge_basis`. `id`, `provider` and uppercase `status` still describe the final Run. POST returns HTTP 200 for a terminal Run and 202 while in flight. Poll the returned `result_url` on the API origin with your Key to retain normalized output and total charges. This read returns HTTP 200 even while pending; check the body. Polling creates no Runs and does not resume fallback. [Get Run](/docs/api-reference/runs/get) keeps the native output and individual charge. Older plugins that only poll Get Run must update their polling path. `COMPLETED` alone does not prove usable content. SEO research returns normalized `output` for every action. List actions expose `output.items[]` with fixed fields per row (for example ranked\_keywords: `keyword`, `position`, `url`, `volume`, `cpc_usd`, `traffic`); overview actions expose fixed top-level fields (for example backlinks\_overview: `backlinks`, `referring_domains`, `semrush_authority_score`, `dataforseo_rank`, `serpstat_domain_rank`, `dofollow_backlinks`, `nofollow_backlinks`). The selected Provider's native output stays on the Run, not in `output`. A value a Provider does not report is `null`; money is always USD. Authority scores are not converted between Providers: each keeps its Provider's own name and scale, and only the answering Provider's field is filled. `volume`, `traffic` and `cpc_usd` are each Provider's own estimates; compare them within one Provider. `result_status` is `success`, `no_result`, `error` or `pending`, and the charge and polling rules above apply unchanged. The field list per action is in the [SEO research](/docs/api-reference/solutions/gtm/seo_research) reference. Company intelligence returns normalized `output` for every action: `enrich` and `traffic` expose fixed top-level fields, `tech_stack`, `competitors`, `news` and `jobs` expose `output.items[]`, `funding` exposes `total_funding_usd` plus `items[]`, and `ads` exposes `total_ads` plus `items[]`. Employee and revenue buckets are split into `*_range_min` / `*_range_max`, and similarity scores carry the Provider's name (`predictleads_similarity_score`, `exa_similarity_score`). The field list per action is in the [Company intelligence](/docs/api-reference/solutions/gtm/company_intelligence) reference. Market data returns normalized `output` for every action with one set of property fields (`address`, `property_type`, `bedrooms`, `bathrooms`, `living_area_sqft`, `lot_size_sqft`, `year_built`, `latitude`, `longitude`). Property search adds owner fields, listings add listing, MLS, HOA, agent and office fields, sale listings use `price_usd` and rental listings `monthly_rent_usd`, and estimates report `comparables_count`. Stock quotes carry `currency`, the regular-session `price`, `change`, `change_percent` (percent points), the `extended_hours_*` quote and `as_of_text`. See the [Market data](/docs/api-reference/solutions/gtm/market_data) reference for the fields per action. Social research returns normalized `output` per mode, shared by all six platforms: one account for `profile`, `output.items[]` of posts for `search` and `feed`, one post for `post`, and `output.profiles[]` for `find`. Posts carry `title`, `text` (the body only) and `published_at`; see the [Social research](/docs/api-reference/solutions/gtm/social_research) reference. People search returns normalized `output` for every action: `search` exposes `total_matches` and `output.items[]`, one row per person, and `enrich` and `find_email` expose one person with the same fields at the top level. Names, job titles, `seniority` and `department` are as the Provider reports them. `email_status` is the Provider's own verification label; read it with `email_catch_all` and `email_source` (Hunter `generated` means the address was built from the domain's pattern). `find_email` without an email is `no_result`. See the [People search](/docs/api-reference/solutions/gtm/people_search) reference for the fields. ## Field conventions Every normalized `output` follows the same naming rules: | Rule | Meaning | | - | - | | Provider-named scores | A value from a Provider's own model or scale (score, rating, rank, difficulty, likelihood, confidence) is named `_`, such as `ahrefs_domain_rating` or `exa_similarity_score`. Only the answering Provider fills it; the others are `null`, and values are never converted between Providers. Labels such as `industry`, `category`, `round` or `intent` keep plain names and use the answering Provider's vocabulary. | | Dates and times | `*_at` is an ISO 8601 UTC timestamp. `*_date` is `YYYY-MM-DD`. `*_text` is display text exactly as returned and is never parsed; relative text such as "3 hours ago" is relative to the Run's `completed_at`. A value that cannot be parsed is `null`, not estimated. | | Domains and URLs | `domain` and `*_domain` are bare hostnames: lower case, without `www.` and without a port. | | Money | A number named `*_usd`. A price in another currency is a number plus a `currency` field. Display prices are `*_text`. | | Counts and ranges | Counts are plain plural nouns. Ranges are `*_min` / `*_max`. A 1-based list order is `position`. | | Empty answers | An empty but valid answer keeps the action's shape: every field is `null`, or the list is `[]`, with `result_status: "no_result"`. This holds whether the Provider sent an empty body or reported "not found" in a way that is not charged, such as a 404 or a "no results" message. It is never `null`, `{}` or the Provider's native body. Web research `scrape` is the one exception: it has no empty answer, and a page that cannot be delivered is an `error` with `output: null`. | | Shared names | Fields with the same meaning and unit have the same name in every capability: `organic_traffic`, `organic_keywords`, `organic_traffic_value_usd`, `published_at`, `source`. | Fetch controls are `formats`, `timeout_ms` (default 30000), `max_charge_usd` (optional) and `cache_max_age_seconds` (optional). Formats guide selection and fallback; available formats appear in the fixed output fields. The Charge cap includes all Runs in this request, including replayed Runs. An unsettled Run stops fallback. Retrying the same key reuses Runs and starts a new request time window. Auto uses Serper then Firecrawl. HTML or explicit cache-age requests go directly to Firecrawl. X/Twitter and LinkedIn enrichment routes are excluded from Firecrawl. Explicit text-only requests use Serper. Exa is available by explicit selection. Firecrawl and Exa use the actual remaining call window with time reserved for settlement and response; less than one second of call time is refused. If no Run can be admitted, the API returns the admission error. If the budget prevents further fallback, it reports the last admitted Run's delivery and all admitted charges. The [Firecrawl Data Sources](/docs/firecrawl) use the same native Run output and do not switch Providers. The Fetch Solution adds routing, structural checks, format checks and a shared request budget. Its search/scrape response follows the normalized contract above. Optional `metadata` stores your tracking values and does not affect Provider selection or Price. # CLI Reference Source: https://glasser.ai/docs/cli Use Glasser from your terminal. Install, sign in, and find the command you need. Search, inspect and run paid API endpoints with one Key — the same three calls as the API, from the terminal. ## Install Requires Node.js 22 or newer; npm is optional. Re-run either command to upgrade. ```bash theme={null} curl -fsSL https://glasser.ai/install.sh | sh # or, with npm: npm install -g @glasser-ai/cli ``` ## Authentication Run this command to open browser sign-in and store a Key for your Workspace: ```bash theme={null} glasser login ``` Approve only when the code in the browser matches the terminal. See [glasser login](/docs/cli/login) for the login options. For CI and scripts, create a Key in the console and set `GLASSER_API_KEY`, or use [glasser keys add](/docs/cli/keys/add). ## Commands Choose a command in the sidebar or open its reference below. Each command page lists its syntax and options. | Command | Description | | - | - | | [`glasser login`](/docs/cli/login) | Log in through the browser and store a Key. | | [`glasser search`](/docs/cli/search) | Search runnable Endpoints or browse Data Sources. | | [`glasser inspect`](/docs/cli/inspect) | Inspect an Endpoint before you run it. | | [`glasser run`](/docs/cli/run) | Run an Endpoint and retrieve its output. | | [`glasser runs list`](/docs/cli/runs/list) | List Runs and filter the results. | | [`glasser runs get`](/docs/cli/runs/get) | Get a Run, wait for completion, or save its output. | | [`glasser runs stop`](/docs/cli/runs/stop) | Request a stop for a Run. | | [`glasser balance`](/docs/cli/balance) | Check your balance and verify your Key. | | [`glasser balance history`](/docs/cli/balance/history) | List balance movements. | | [`glasser keys add`](/docs/cli/keys/add) | Store a Key on this machine. | | [`glasser keys list`](/docs/cli/keys/list) | List stored Keys. | | [`glasser keys activate`](/docs/cli/keys/activate) | Switch the active Key. | | [`glasser keys remove`](/docs/cli/keys/remove) | Remove a Key from this machine. | | [`glasser skill install`](/docs/cli/skill/install) | Save the Skill so new agent sessions load it. | ## Keep calls in one Task A search returns a `task_id`. Pass that value with `--task` on related searches, including retries with different words and requests for the next page, and on `inspect` and `run`. The CLI does not store or reuse the Task automatically. Every search still requires `--use-case`, even when you pass `--task`. ```bash theme={null} glasser search "company enrichment" --use-case "Prepare a company profile" ``` Replace `` below with the `task_id` from that response. Use the Provider, Endpoint, and input selected through search and inspection. ```bash theme={null} glasser inspect -p -e --task glasser run -p -e -i '' --task glasser runs list --task ``` Omitting `--task` starts a new Task on each search. On `inspect` and `run`, omitting it leaves the call without a Task. On `runs list`, `--task` filters the results to that Task. ## Global flags Global flags on every command: `-j/--json`, `--help`, `--version`. ## JSON mode With `-j/--json`, command results on stdout are JSON. Stderr is empty on success and contains one JSON error object on failure. Explicit `--help` and `--version` requests still produce text. * `run --json` requires `--idempotency-key` so you can retry with the same key. * `keys remove --json` requires `--force` to skip interactive confirmation. * `login --json` is a usage error because login is interactive. * `--output` saves only the Run's output field. On a successful write, stdout contains the full Run. A file write failure leaves stdout empty, writes an `io_error` JSON object to stderr, and exits `1`. JSON mode does not print file status messages to stderr. For `run` and `runs get`, a `FAILED` or `STOPPED` Run is still returned on stdout. The command also writes a JSON error to stderr and exits with code `1`. Money amounts in Glasser response fields are exact decimal strings, never floats. ## Exit codes | Code | Meaning | | - | - | | `0` | Success | | `1` | API, network, or local I/O failure; wait timeout; or `run` / `runs get` returned a `FAILED` or `STOPPED` Run | | `2` | Usage error — bad flags or bad input; the command never reached the API | | `130` | Interrupted (Ctrl-C) | For `run` and `runs get`, exit `0` can mean that the Run is still `QUEUED` or `RUNNING` when you do not use `--wait`. A `COMPLETED` Run also exits `0` when the Provider returned HTTP 4xx or 5xx; check `provider_response.http_status`. The Run's status and `charge_usd` are separate results. `runs stop` exits `0` when the stop request is accepted, even if the Run is still running. See [stopping a Run](/docs/cli/runs/stop) for the full behavior. ## Environment variables | Variable | Meaning | | - | - | | `GLASSER_API_KEY` | A Key for this invocation; overrides the local key store | | `GLASSER_API_BASE_URL` | API origin (default [https://api.glasser.ai](https://api.glasser.ai)) | | `NO_COLOR` | Disable colour in the help and version text the CLI framework renders | ## For agents The agent-facing Skill at [glasser.ai/SKILL.md](https://glasser.ai/SKILL.md) packages this CLI — when to use it, how to authenticate through `glasser login`, and the rules that keep spending deliberate. Point your agent at that file. # glasser balance Source: https://glasser.ai/docs/cli/balance Check your balance and verify your Key. ## Usage ```bash theme={null} glasser balance ``` This free request returns three amounts: | Amount | Meaning | | - | - | | Balance | Settled funds in your Workspace. | | Held | Funds reserved for unfinished Runs. | | Available | Balance minus held; the funds you can use for new Runs. | Exit `0` confirms that your Key works, even when the balance is zero. See [CLI conventions](/docs/cli#global-flags) for global flags, JSON mode, exit codes, and environment variables. # glasser balance history Source: https://glasser.ai/docs/cli/balance/history List balance movements. ## Usage ```bash theme={null} glasser balance history ``` List every balance movement, newest first. Amounts are exact decimal strings. ## Flags | Flag | Description | | - | - | | `--limit` | Maximum items to return (1-100; default 20) | | `--cursor` | Pagination cursor from a previous response | | `--kind` | Filter by kind: charge, refund, topup, grant, adjustment | See [CLI conventions](/docs/cli#global-flags) for global flags, JSON mode, exit codes, and environment variables. # glasser inspect Source: https://glasser.ai/docs/cli/inspect Inspect an Endpoint before you run it. ## Usage ```bash theme={null} glasser inspect -p -e ``` Inspect one endpoint: the provider-native input schema, the price with every charge clause, and the current version. Read this before you run anything. ## Flags | Flag | Description | | - | - | | `--provider, -p` | Provider slug (e.g. pdl) | | `--endpoint, -e` | Endpoint key (e.g. /v5/person/enrich) | | `--endpoint-version` | Select a supported Endpoint version (does not lock Price; 409 if unavailable or retired) | | `--task` | Associate this inspection with the `task_id` from a search response | The CLI does not reuse a Task automatically. See [keeping calls in one Task](/docs/cli#keep-calls-in-one-task). See [CLI conventions](/docs/cli#global-flags) for global flags, JSON mode, exit codes, and environment variables. # glasser keys activate Source: https://glasser.ai/docs/cli/keys/activate Switch the active Key. ## Usage ```bash theme={null} glasser keys activate -l