get_agent_capabilities
Return the Loppee agent contract, endpoints, policy rules, and available MCP tools.
Parameters
No parameters.
Raw schema
{
"type": "object",
"properties": {}
}by loppee
Agent-first US business trust registry with neutral Trust Cards and local search.
Agent-first US business trust registry with neutral Trust Cards and local search.
Captured live from the server via tools/list.
Return the Loppee agent contract, endpoints, policy rules, and available MCP tools.
Parameters
No parameters.
{
"type": "object",
"properties": {}
}Return Loppee's own published pricing for its paid-exposure plans (Free/Silver/Gold/Platinum/Diamond): prices, feature bullets, multi-location branch add-ons, and any currently-running promotions. This is the same published document the public /pricing page renders (also available as GET /v1/pricing). Paid plans buy discovery reach and product features only — pricing and promotions never change trust_score, safe_to_recommend, verification, review weighting, or ranking order.
Parameters
No parameters.
{
"type": "object",
"properties": {}
}Backward-compatible discovery search that deterministically auto-routes free text. If q/category resolves to Loppee's closed taxonomy vocabulary, it uses the reach-gated category path (paid reach + claimed/free 1-mile organic reach, plus deliberately published unclaimed discovery listings marked discovery_listed=true — real registry records, unverified, never recommendable, ranked after every published result; raw seeds outside that published set are never queried). If it does not resolve, it uses universal business-name lookup where existence is pay-independent and bounded unclaimed seeds can appear. Colloquial category phrasings resolve too (e.g. 'ac repair' → HVAC); on a zero-result query the response includes a structured suggestions block — suggestions.categories (nearest taxonomy categories, typo-tolerant did-you-mean, e.g. 'plumer' → plumber), suggestions.did_you_mean (the corrected phrase), and suggestions.relaxed_query — retry with a suggested category alias or the corrected phrase instead of reporting a dead end. Location: pass lat/lng (with optional radius_miles), zip, or city+state; when NONE is provided, category browse falls back to the requester's coarse IP-derived location (approximate, city-level, disclosed in the response's location_context) — pass the user's explicit location whenever it is known. Placement can be commercially influenced through disclosed share-of-voice; payment never changes trust_score, safe_to_recommend, verification, or name existence.
Parameters
| q | string | optional | Free-text search. Category terms auto-route to the taxonomy category path; otherwise this is a universal business-name lookup. |
| category | string | optional | Taxonomy category alias or category term. When it resolves, search uses the category path. |
| intent | string | optional | Routing hint. auto resolves taxonomy first; category forces reach-gated taxonomy discovery; name forces universal business-name lookup. |
| city | string | optional | City filter. |
| state | string | optional | Two-letter US state filter. |
| zip | string | optional | 5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng). |
| lat | number | optional | Requester latitude for distance-aware search. |
| lng | number | optional | Requester longitude for distance-aware search. |
| radius_miles | number | optional | Maximum distance in miles when lat/lng are provided. |
| safe_to_recommend | boolean | optional | When true, return only records safe for automated recommendation. |
| include_directory_listings | boolean | optional | Include unverified directory listings for discovery. |
| location_confidence | string | optional | How well the passed lat/lng reflect the USER's real position: precise (device fix) or coarse (city-level geocode). Coarse widens the FREE-discovery reach honestly (adaptive free reach); paid radii, ranking, and trust are never affected. |
| limit | integer | optional | Maximum result count. |
{
"type": "object",
"properties": {
"q": {
"description": "Free-text search. Category terms auto-route to the taxonomy category path; otherwise this is a universal business-name lookup.",
"type": "string"
},
"category": {
"description": "Taxonomy category alias or category term. When it resolves, search uses the category path.",
"type": "string"
},
"intent": {
"default": "auto",
"description": "Routing hint. auto resolves taxonomy first; category forces reach-gated taxonomy discovery; name forces universal business-name lookup.",
"type": "string",
"enum": [
"auto",
"category",
"name"
]
},
"city": {
"description": "City filter.",
"type": "string"
},
"state": {
"description": "Two-letter US state filter.",
"type": "string"
},
"zip": {
"description": "5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng).",
"type": "string"
},
"lat": {
"description": "Requester latitude for distance-aware search.",
"type": "number"
},
"lng": {
"description": "Requester longitude for distance-aware search.",
"type": "number"
},
"radius_miles": {
"description": "Maximum distance in miles when lat/lng are provided.",
"type": "number",
"exclusiveMinimum": 0
},
"safe_to_recommend": {
"description": "When true, return only records safe for automated recommendation.",
"type": "boolean"
},
"include_directory_listings": {
"default": true,
"description": "Include unverified directory listings for discovery.",
"type": "boolean"
},
"location_confidence": {
"description": "How well the passed lat/lng reflect the USER's real position: precise (device fix) or coarse (city-level geocode). Coarse widens the FREE-discovery reach honestly (adaptive free reach); paid radii, ranking, and trust are never affected.",
"type": "string",
"enum": [
"precise",
"coarse"
]
},
"limit": {
"default": 10,
"description": "Maximum result count.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}Reach-gated category/area discovery using Loppee taxonomy aliases and synonyms. This read-only tool queries the category aliases of published Trust-Card businesses plus deliberately published unclaimed discovery listings (marked discovery_listed=true — real registry records, unverified, never recommendable, ranked after every published result); raw seeds outside that published discovery set cannot appear. Common colloquial phrasings resolve (e.g. 'ac repair' or 'furnace repair' → HVAC, 'exterminator' → pest control); when a term does not resolve or matches nothing, the response includes suggestions.categories (nearest taxonomy categories, typo-tolerant — 'plumer' suggests plumber) and suggestions.did_you_mean — retry with one of those aliases instead of treating the miss as final. Location: pass lat/lng (with optional radius_miles), zip, or city+state; when NONE is provided, results fall back to the requester's coarse IP-derived location (approximate, city-level, disclosed in location_context) — pass the user's explicit location whenever it is known. Payment buys only discovery reach and disclosed share-of-voice placement; it never changes trust_score, safe_to_recommend, verification, or category assignment.
Parameters
| category | string | required | Taxonomy category alias or natural category term, such as plumber, restaurants, notary public, or home_property. |
| city | string | optional | City filter. |
| state | string | optional | Two-letter US state filter. |
| zip | string | optional | 5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng). |
| lat | number | optional | Requester latitude for distance-aware category discovery. |
| lng | number | optional | Requester longitude for distance-aware category discovery. |
| radius_miles | number | optional | Maximum distance in miles when lat/lng are provided. |
| safe_to_recommend | boolean | optional | When true, return only records safe for automated recommendation. |
| location_confidence | string | optional | How well the passed lat/lng reflect the USER's real position: precise (device fix) or coarse (city-level geocode). Coarse widens the FREE-discovery reach honestly (adaptive free reach); paid radii, ranking, and trust are never affected. |
| limit | integer | optional | Maximum result count. |
{
"type": "object",
"properties": {
"category": {
"type": "string",
"description": "Taxonomy category alias or natural category term, such as plumber, restaurants, notary public, or home_property."
},
"city": {
"description": "City filter.",
"type": "string"
},
"state": {
"description": "Two-letter US state filter.",
"type": "string"
},
"zip": {
"description": "5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng).",
"type": "string"
},
"lat": {
"description": "Requester latitude for distance-aware category discovery.",
"type": "number"
},
"lng": {
"description": "Requester longitude for distance-aware category discovery.",
"type": "number"
},
"radius_miles": {
"description": "Maximum distance in miles when lat/lng are provided.",
"type": "number",
"exclusiveMinimum": 0
},
"safe_to_recommend": {
"description": "When true, return only records safe for automated recommendation.",
"type": "boolean"
},
"location_confidence": {
"description": "How well the passed lat/lng reflect the USER's real position: precise (device fix) or coarse (city-level geocode). Coarse widens the FREE-discovery reach honestly (adaptive free reach); paid radii, ranking, and trust are never affected.",
"type": "string",
"enum": [
"precise",
"coarse"
]
},
"limit": {
"default": 10,
"description": "Maximum result count.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"category"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Universal business-name lookup. This read-only tool is pay-independent: claimed, paid, free, and bounded unclaimed open-data seed records remain findable by name. It does not use payment, trust score, or category reach to decide whether a named business exists.
Parameters
| name | string | required | Business name to look up. This path is universal and pay-independent, including unclaimed open-data seeds when the name lookup is bounded. |
| city | string | optional | Optional city filter. |
| state | string | optional | Optional two-letter US state filter. |
| zip | string | optional | 5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng). |
| lat | number | optional | Requester latitude for distance annotation. |
| lng | number | optional | Requester longitude for distance annotation. |
| radius_miles | number | optional | Maximum distance in miles when lat/lng are provided. |
| limit | integer | optional | Maximum result count. |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Business name to look up. This path is universal and pay-independent, including unclaimed open-data seeds when the name lookup is bounded."
},
"city": {
"description": "Optional city filter.",
"type": "string"
},
"state": {
"description": "Optional two-letter US state filter.",
"type": "string"
},
"zip": {
"description": "5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng).",
"type": "string"
},
"lat": {
"description": "Requester latitude for distance annotation.",
"type": "number"
},
"lng": {
"description": "Requester longitude for distance annotation.",
"type": "number"
},
"radius_miles": {
"description": "Maximum distance in miles when lat/lng are provided.",
"type": "number",
"exclusiveMinimum": 0
},
"limit": {
"default": 10,
"description": "Maximum result count.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"required": [
"name"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}The trustworthy-opinion endpoint: returns only published Loppee Trust Card profiles with safe_to_recommend=true. Quality comes first within each pool, but placement IS commercially influenced and disclosed honestly as commercial_influence:"sponsored_share_of_voice". Payment NEVER changes a business's trust_score, the evidence behind it, or its safe_to_recommend decision. What payment affects is placement: eligible results are split into a paying pool and a free pool and interleaved ~80/20 (4 paying : 1 free per page of five), and within each pool they are ordered by displayed-rating band (higher first) then rotated by how often they've recently been shown, so higher tiers earn proportionally more visibility and no business is permanently first. WITHIN the same pool a lower-rated business can never outrank a higher-rated one; ACROSS the 80/20 split a lower-rated PAYING business CAN appear above a higher-rated FREE one — so don't treat absolute position as a pure quality ranking. Payment also buys discovery reach (radius). Use this — not search_businesses — when a user needs a business you will actually recommend. Directory listings and unverified seed records are excluded. Each result includes the trust_card_url to fetch full evidence and a citation. Returns an empty results array (not an error) when nothing qualifies — say so rather than falling back to unverified sources.
Parameters
| q | string | optional | Free-text search across name, category, city, state, website, and source. |
| category | string | optional | Business category such as Restaurants, HVAC, Health, Legal, or Automotive. |
| city | string | optional | City filter. |
| state | string | optional | Two-letter US state filter. |
| zip | string | optional | 5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng). |
| lat | number | optional | Requester latitude for distance-aware recommendation filtering. |
| lng | number | optional | Requester longitude for distance-aware recommendation filtering. |
| radius_miles | number | optional | Maximum distance in miles when lat/lng are provided. |
| allowed_action | string | optional | Require a specific allowed action such as recommend, call_business, or request_quote. |
| min_score | integer | optional | Minimum trust score. |
| confidence | string | optional | Confidence filter such as high, medium, low, or unknown. |
| risk_level | string | optional | Risk-level filter such as verified_low_risk or verified_with_warnings. |
| limit | integer | optional | Maximum result count. |
{
"type": "object",
"properties": {
"q": {
"description": "Free-text search across name, category, city, state, website, and source.",
"type": "string"
},
"category": {
"description": "Business category such as Restaurants, HVAC, Health, Legal, or Automotive.",
"type": "string"
},
"city": {
"description": "City filter.",
"type": "string"
},
"state": {
"description": "Two-letter US state filter.",
"type": "string"
},
"zip": {
"description": "5-digit US ZIP; resolved to its ZCTA centroid and treated as a located search (~25mi default radius, same semantics as lat/lng).",
"type": "string"
},
"lat": {
"description": "Requester latitude for distance-aware recommendation filtering.",
"type": "number"
},
"lng": {
"description": "Requester longitude for distance-aware recommendation filtering.",
"type": "number"
},
"radius_miles": {
"description": "Maximum distance in miles when lat/lng are provided.",
"type": "number",
"exclusiveMinimum": 0
},
"allowed_action": {
"description": "Require a specific allowed action such as recommend, call_business, or request_quote.",
"type": "string"
},
"min_score": {
"description": "Minimum trust score.",
"type": "integer",
"minimum": 0,
"maximum": 100
},
"confidence": {
"description": "Confidence filter such as high, medium, low, or unknown.",
"type": "string"
},
"risk_level": {
"description": "Risk-level filter such as verified_low_risk or verified_with_warnings.",
"type": "string"
},
"limit": {
"default": 10,
"description": "Maximum result count.",
"type": "integer",
"minimum": 1,
"maximum": 50
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}Discover active schema.org-aligned Loppee Jobs postings from claimed, verified, published employer Trust Cards. Results include JobPosting JSON-LD. Location: pass lat/lng (with radius_miles), zip, or city+state; when NONE is provided, results fall back to the requester's coarse IP-derived location (approximate, city-level, disclosed in location_context; remote roles are always included unless include_remote=false) — pass the user's explicit location whenever it is known. Payment controls posting eligibility only; it never ranks jobs, changes trust score, or changes business recommendation order.
Parameters
| q | string | optional | Role/keyword search across job title, description, category, skills, experience, and location. Typo-tolerant (trigram word similarity). |
| category | string | optional | Field/domain filter resolved against the same closed category taxonomy as businesses (aliases + synonyms, e.g. 'hvac' or 'ac repair'); unresolvable terms fall back to free-text category matching. |
| city | string | optional | City filter. |
| state | string | optional | Two-letter US state filter. |
| zip | string | optional | 5-digit US ZIP filter, matched against the posting's postal code. |
| lat | number | optional | Latitude for radius search (use with lng and radius_miles). |
| lng | number | optional | Longitude for radius search. |
| radius_miles | number | optional | Radius in miles around lat/lng. Remote roles are included regardless of distance unless include_remote=false. |
| workplace_type | string | optional | Workplace type. |
| employment_type | string | optional | Employment type. |
| experience_level | string | optional | Experience-level filter (substring match, e.g. 'entry', 'senior'). |
| salary_min | number | optional | Annualized USD salary floor (hourly salaries compare at x2080, monthly at x12). Jobs without a disclosed salary are excluded when set. |
| salary_max | number | optional | Annualized USD salary ceiling. |
| posted_within_days | integer | optional | Only roles published within the last N days. |
| include_remote | boolean | optional | Default true: remote roles bypass ZIP/radius location filters. Set false to exclude remote roles from located searches. |
| sort | string | optional | Result ordering; both are commercially neutral. Default relevance (text/location fit + recency). |
| job_id | string | optional | Exact posting lookup — the id behind the /jobs/{job_id} page. |
| limit | integer | optional | Maximum result count. |
| offset | integer | optional | Pagination offset into the ranked result set. |
{
"type": "object",
"properties": {
"q": {
"description": "Role/keyword search across job title, description, category, skills, experience, and location. Typo-tolerant (trigram word similarity).",
"type": "string"
},
"category": {
"description": "Field/domain filter resolved against the same closed category taxonomy as businesses (aliases + synonyms, e.g. 'hvac' or 'ac repair'); unresolvable terms fall back to free-text category matching.",
"type": "string"
},
"city": {
"description": "City filter.",
"type": "string"
},
"state": {
"description": "Two-letter US state filter.",
"type": "string"
},
"zip": {
"description": "5-digit US ZIP filter, matched against the posting's postal code.",
"type": "string"
},
"lat": {
"description": "Latitude for radius search (use with lng and radius_miles).",
"type": "number"
},
"lng": {
"description": "Longitude for radius search.",
"type": "number"
},
"radius_miles": {
"description": "Radius in miles around lat/lng. Remote roles are included regardless of distance unless include_remote=false.",
"type": "number",
"exclusiveMinimum": 0
},
"workplace_type": {
"description": "Workplace type.",
"type": "string",
"enum": [
"on_site",
"hybrid",
"remote"
]
},
"employment_type": {
"description": "Employment type.",
"type": "string",
"enum": [
"full_time",
"part_time",
"contract",
"temporary",
"internship",
"seasonal"
]
},
"experience_level": {
"description": "Experience-level filter (substring match, e.g. 'entry', 'senior').",
"type": "string"
},
"salary_min": {
"description": "Annualized USD salary floor (hourly salaries compare at x2080, monthly at x12). Jobs without a disclosed salary are excluded when set.",
"type": "number",
"minimum": 0
},
"salary_max": {
"description": "Annualized USD salary ceiling.",
"type": "number",
"minimum": 0
},
"posted_within_days": {
"description": "Only roles published within the last N days.",
"type": "integer",
"minimum": 1,
"maximum": 365
},
"include_remote": {
"description": "Default true: remote roles bypass ZIP/radius location filters. Set false to exclude remote roles from located searches.",
"type": "boolean"
},
"sort": {
"description": "Result ordering; both are commercially neutral. Default relevance (text/location fit + recency).",
"type": "string",
"enum": [
"relevance",
"newest"
]
},
"job_id": {
"description": "Exact posting lookup — the id behind the /jobs/{job_id} page.",
"type": "string"
},
"limit": {
"default": 10,
"description": "Maximum result count.",
"type": "integer",
"minimum": 1,
"maximum": 50
},
"offset": {
"description": "Pagination offset into the ranked result set.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}Fetch the full Trust Card for one published business by business_id or domain_key — use this to verify, justify, or cite a specific business before acting. Includes the trust score, evidence breakdown, recommendation_rationale (the machine 'why'), commercial_neutrality, allowed_actions, and a ready-to-use citation. Returns an error for unpublished, blocked, or unknown records.
Parameters
| business_id | string | optional | Loppee business id. |
| domain_key | string | optional | Normalized domain key such as example-com. |
{
"type": "object",
"properties": {
"business_id": {
"description": "Loppee business id.",
"type": "string"
},
"domain_key": {
"description": "Normalized domain key such as example-com.",
"type": "string"
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}Read the published customer reviews of one business, server-paginated and filterable by star rating — the SAME data and controls a human gets on the profile's Reviews section (also served as GET /v1/businesses/{business_id}/reviews.json with ?page=&limit=&rating=). Page through with page (1-based, default 1) and limit (1-50, default 5; pagination.has_more/next_page say when to keep going), and pass ratings (e.g. [1] for only 1-star, [4,5] for 4-and-5-star) to read chosen star levels; summary.rating_counts gives the per-star totals so you can decide which levels to read. Reviews are DISPLAY-ONLY social proof: reading, paging, or filtering them NEVER changes the business's trust score, search ranking, reach, or share-of-voice, and the newest-first order carries no ranking meaning. Reviewer names are masked (first name + last initial) — no PII. The Trust Card embeds only the newest slice of reviews; use this tool to read the full set. Returns business_reviews_not_found for unpublished or unknown ids and invalid_rating_filter for a malformed ratings value.
Parameters
| business_id | string | required | Loppee business id of a published business. |
| page | integer | optional | 1-based page number (default 1). |
| limit | integer | optional | Reviews per page (default 5, max 50). |
| ratings | array | optional | Star-rating filter: return only reviews with these ratings, e.g. [1] or [4,5]. Omit for all ratings. |
{
"type": "object",
"properties": {
"business_id": {
"type": "string",
"minLength": 1,
"description": "Loppee business id of a published business."
},
"page": {
"description": "1-based page number (default 1).",
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"limit": {
"description": "Reviews per page (default 5, max 50).",
"type": "integer",
"minimum": 1,
"maximum": 50
},
"ratings": {
"description": "Star-rating filter: return only reviews with these ratings, e.g. [1] or [4,5]. Omit for all ratings.",
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 5
}
}
},
"required": [
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Return the structured 'why' behind Loppee's recommend/not-recommend decision for one published business, in a single call — so an agent can justify a pick without re-fetching and parsing the whole Trust Card. Includes decision, safe_to_recommend, the publishing_rule, score vs threshold, verified/total evidence, the human-readable basis, agent_readiness, commercial_neutrality, and a ready-to-use citation. Returns an error for unpublished, blocked, or unknown records.
Parameters
| business_id | string | required | Loppee business id of a published Trust Card. |
{
"type": "object",
"properties": {
"business_id": {
"type": "string",
"minLength": 1,
"description": "Loppee business id of a published Trust Card."
}
},
"required": [
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Normalized side-by-side of 2 or more published businesses so an agent can rank candidates without one call per business. Each row carries trust_score, safe_to_recommend, verification_status, risk_level, confidence, verified/total evidence, agent readiness, and commercial_status. UNLIKE recommend_businesses, this ranking is strictly NEUTRAL (commercial_influence:"none"): rows are ordered purely by trust (safe_to_recommend, then trust_score, then confidence, then name) with NO share-of-voice rotation and NO paying/free pools — commercial status is never read. Use compare_businesses when you want an unbiased quality ranking of a known candidate set. Ids that are not published Trust Cards are returned under unresolved_business_ids instead of being ranked.
Parameters
| business_ids | array | required | Two to twenty Loppee business ids to compare. Duplicates are de-duplicated. |
{
"type": "object",
"properties": {
"business_ids": {
"minItems": 2,
"maxItems": 20,
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"description": "Two to twenty Loppee business ids to compare. Duplicates are de-duplicated."
}
},
"required": [
"business_ids"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Identify the calling agent from its API key: returns the account_id, label, and the exact allowed_actions this key may perform. Call this first to confirm a key is wired correctly and to discover this agent's permissions before attempting any write tool. Requires a valid agent API key (X-LOPPEE-API-Key or Authorization: Bearer); returns an auth error when the key is missing or revoked.
Parameters
No parameters.
{
"type": "object",
"properties": {}
}Immediately and irreversibly revoke the API key THIS call authenticates with — the agent-side 'delete my key' for connection hygiene (e.g. the key may be exposed, the integration is being retired, or the user asked to disconnect). Possession of the key is the authorization: it can only ever revoke itself, never another key or account, and it removes access rather than granting any. Takes effect on the next request (key validation is a live database check, so there is no cache window). The revocation is written to the audit log before the key is disabled. Requires confirm:true — without it the tool returns confirm_required and changes nothing. A new key can only be issued by the account's human owner from their Loppee dashboard (or by an admin); this tool cannot mint keys. Operator keys configured in the server environment return env_key_not_revocable. Call get_agent_identity first if you need to confirm which account and label this key belongs to.
Parameters
| confirm | boolean | required |
{
"type": "object",
"properties": {
"confirm": {
"type": "boolean"
}
},
"required": [
"confirm"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Attach a published business or directory listing to a customer/service-agent account workflow (a shortlist — it does not contact the business). The shortlist round-trips: read it back with list_saved_businesses and prune entries with unsave_business. Requires a valid scoped agent API key whose account_id matches the account_id argument and whose allowed_actions include save_business; call get_agent_identity first to confirm scope. Idempotent: saving the same business twice is a no-op. Saving never affects the business's trust score, ranking, or reviews. Returns a machine-readable auth error (missing_api_key / forbidden_account) when the key is absent or out of scope.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| business_name | string | required | |
| business_source | string | required | |
| category | string | optional | |
| city | string | optional | |
| state | string | optional | |
| notes | string | optional |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"business_name": {
"type": "string",
"minLength": 1
},
"business_source": {
"type": "string",
"minLength": 1
},
"category": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"notes": {
"type": "string"
}
},
"required": [
"account_id",
"business_id",
"business_name",
"business_source"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List the calling account's OWN saved-business shortlist, newest first — the read half of save_business, so an agent can review and report the shortlist it has built. Returns business_id, business_name, business_source, category, city, state, notes, and saved_at for up to 100 entries (default 20, newest-first, no cursor). Requires a valid scoped agent API key whose account_id matches the account_id argument (call get_agent_identity first); keys scoped to save_business may also read. Read-only: never modifies the shortlist and never affects any business's trust score or ranking. Returns a machine-readable auth error (invalid_agent_api_key / agent_account_scope_violation) when the key is absent or out of scope.
Parameters
| account_id | string | required | The customer/service-agent account id this key belongs to (confirm with get_agent_identity). |
| limit | integer | optional | Max shortlist entries to return (default 20). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer/service-agent account id this key belongs to (confirm with get_agent_identity)."
},
"limit": {
"description": "Max shortlist entries to return (default 20).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Remove one business from the calling account's OWN saved-business shortlist — the prune half of save_business. Idempotent: unsaving a business that is not on the shortlist is a no-op that returns removed=false, never an error. This only edits the account's own shortlist; it does not contact the business and never affects the business's trust score, ranking, or reviews. Requires a valid scoped agent API key whose account_id matches the account_id argument and whose allowed_actions include unsave_business (keys scoped to save_business may also unsave; call get_agent_identity first). Returns a machine-readable auth error (invalid_agent_api_key / agent_account_scope_violation) when the key is absent or out of scope.
Parameters
| account_id | string | required | The customer/service-agent account id this key belongs to (confirm with get_agent_identity). |
| business_id | string | required | The saved business to remove from the shortlist. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer/service-agent account id this key belongs to (confirm with get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The saved business to remove from the shortlist."
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Read the calling customer account's saved home location (ZIP or precise point + label) — the persistent discovery anchor that search/recommend tools use automatically for this customer when no explicit location is passed. Discovery anchor ONLY: it never affects any business's trust score, ranking, or reviews. Requires a valid scoped customer personal-agent key whose account_id matches the account_id argument (call get_agent_identity first). Returns available=false when nothing is saved.
Parameters
| account_id | string | required | The customer account id this personal-agent key belongs to (confirm with get_agent_identity). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer account id this personal-agent key belongs to (confirm with get_agent_identity)."
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Save or replace the calling customer account's home location: EITHER a 5-digit US zip (validated against the Census gazetteer) OR latitude+longitude, optionally with a label like 'Home'. Once saved it becomes the customer's DEFAULT discovery anchor — search_businesses/search_category/search_jobs and /v1/search anchor on it automatically for this customer whenever no explicit location is passed (explicit lat/lng/zip/city always win). Confirm the location with the user before saving. Discovery anchor ONLY — never a ranking, trust, or review input. Requires a valid scoped customer personal-agent key whose account_id matches the account_id argument.
Parameters
| account_id | string | required | The customer account id this personal-agent key belongs to (confirm with get_agent_identity). |
| zip | string | optional | 5-digit US ZIP to save as the customer's home location (validated against the Census gazetteer). Provide EITHER zip OR latitude+longitude. |
| latitude | number | optional | Precise latitude to save (with longitude). |
| longitude | number | optional | Precise longitude to save (with latitude). |
| label | string | optional | Optional human label, e.g. 'Home' or 'Office'. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer account id this personal-agent key belongs to (confirm with get_agent_identity)."
},
"zip": {
"description": "5-digit US ZIP to save as the customer's home location (validated against the Census gazetteer). Provide EITHER zip OR latitude+longitude.",
"type": "string"
},
"latitude": {
"description": "Precise latitude to save (with longitude).",
"type": "number"
},
"longitude": {
"description": "Precise longitude to save (with latitude).",
"type": "number"
},
"label": {
"description": "Optional human label, e.g. 'Home' or 'Office'.",
"type": "string",
"maxLength": 80
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Remove the calling customer account's saved home location. Idempotent: clearing when nothing is saved returns available=false, never an error. After clearing, location-less searches for this customer fall back to the coarse IP-derived default. Requires a valid scoped customer personal-agent key whose account_id matches the account_id argument.
Parameters
| account_id | string | required | The customer account id this personal-agent key belongs to (confirm with get_agent_identity). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer account id this personal-agent key belongs to (confirm with get_agent_identity)."
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Send a message to a business on behalf of the calling customer account. The message is delivered DIRECTLY to the business owner's Loppee inbox — there is no human pre-moderation and no delivery delay, so you may tell the user the business has been messaged. Only PUBLISHED businesses on a paid tier accept messages (business_not_messageable / customer_chat_unavailable otherwise); the stored business name is resolved from the registry, never from target_business_name. A blocked attempt against a free or unclaimed business is recorded for the owner as a MISSED CONTACT (the 403/404 error says so when it happens): the message is NOT delivered, but if the business upgrades the owner can read it and reply — tell the user their message was not delivered but was recorded in case the business joins. Do not retry a blocked send. Repeat sends to the same business append to the one ongoing conversation thread; read replies with list_my_conversations. Subject is capped at 160 characters and the message at 4000. Requires a valid scoped agent API key whose account_id matches the account_id argument and whose allowed_actions include send_message_request (call get_agent_identity first). Returns a machine-readable auth error when the key is absent or out of scope. Sending a message never affects the business's trust score, ranking, or review weighting.
Parameters
| account_id | string | required | |
| target_business_id | string | required | |
| target_business_name | string | required | |
| target_business_source | string | required | |
| subject | string | required | |
| message | string | required |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"target_business_id": {
"type": "string",
"minLength": 1
},
"target_business_name": {
"type": "string",
"minLength": 1
},
"target_business_source": {
"type": "string",
"minLength": 1
},
"subject": {
"type": "string",
"minLength": 1
},
"message": {
"type": "string",
"minLength": 1,
"maxLength": 4000
}
},
"required": [
"account_id",
"target_business_id",
"target_business_name",
"target_business_source",
"subject",
"message"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List the calling customer account's OWN message conversations with businesses, newest first, each including the business's replies — the read half of send_message_request, so an agent can report answers back to its user. Requires a valid scoped agent API key whose account_id matches the account_id argument (call get_agent_identity first); keys scoped to send_message_request may also read. Read-only: never modifies anything.
Parameters
| account_id | string | required | |
| limit | integer | optional | Max conversations to return (default 20). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"limit": {
"description": "Max conversations to return (default 20).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Submit (or edit) a first-party customer/service-agent review (rating 1-5) for a business. The review is from a REGISTERED identity and is published immediately — there is no anonymous review and no pre-moderation. There is at most ONE review per (account, business): submitting again EDITS the existing review (idempotent on that pair). Star reviews are DISPLAY-ONLY social proof: they NEVER change the business's trust score, search ranking, reach, or share-of-voice, and payment never changes how a review is displayed. A review backed by a Loppee-verified transaction between this account and the business carries a 'Verified transaction' badge (authenticity display only); sending messages through Loppee does NOT earn that badge. A review is removed only by a human moderator for a recorded policy violation, never for being negative. Requires a valid scoped agent API key whose account_id matches the account_id argument and whose allowed_actions include submit_review_for_moderation (call get_agent_identity first). Returns a machine-readable auth error when the key is absent or out of scope.
Parameters
| account_id | string | required | |
| target_business_id | string | required | |
| target_business_name | string | required | |
| target_business_source | string | required | |
| rating | integer | required | |
| subject | string | required | |
| message | string | required |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"target_business_id": {
"type": "string",
"minLength": 1
},
"target_business_name": {
"type": "string",
"minLength": 1
},
"target_business_source": {
"type": "string",
"minLength": 1
},
"rating": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"subject": {
"type": "string",
"minLength": 1
},
"message": {
"type": "string",
"minLength": 1,
"maxLength": 4000
}
},
"required": [
"account_id",
"target_business_id",
"target_business_name",
"target_business_source",
"rating",
"subject",
"message"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Apply to an active Loppee job on behalf of the calling customer account. Requires a customer personal agent key whose account_id matches the account_id argument and whose allowed_actions include apply_to_job. The seeker is never charged. The resume must be a base64 PDF, DOC, or DOCX file and is stored in a private bucket; employers and the applicant retrieve it only through scoped short-lived signed URLs.
Parameters
| account_id | string | required | |
| job_id | string | required | |
| cover_note | string | optional | |
| resume | object | required |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"job_id": {
"type": "string",
"minLength": 1
},
"cover_note": {
"type": "string",
"maxLength": 4000
},
"resume": {
"type": "object",
"properties": {
"file_name": {
"type": "string",
"minLength": 1
},
"content_type": {
"type": "string",
"enum": [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
]
},
"size_bytes": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"data_base64": {
"type": "string",
"minLength": 1
}
},
"required": [
"file_name",
"content_type",
"size_bytes",
"data_base64"
]
}
},
"required": [
"account_id",
"job_id",
"resume"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List the calling customer account's OWN job applications, newest first — the read half of apply_to_job, so an agent can report what happened to each application. Each entry carries the employer-set status (submitted, viewed, shortlisted, rejected, hired, or withdrawn), a job + employer summary, the cover note, and — when a resume is attached — a short-lived signed resume_url (about 5 minutes; re-list to refresh, resume_url is null if signing fails). Optional status filter and offset pagination (limit up to 50, default 20). Requires a customer personal agent key whose account_id matches the account_id argument (call get_agent_identity first); keys minted before this tool existed may read with apply_to_job scope. Read-only: listing never changes an application's status and never affects any employer's trust score or ranking — application status is set by the employer, never by this tool.
Parameters
| account_id | string | required | The customer account id this personal-agent key belongs to (confirm with get_agent_identity). |
| status | string | optional | Only return applications currently in this employer-set status. |
| limit | integer | optional | Max applications to return (default 20). |
| offset | integer | optional | Pagination offset into the newest-first list. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer account id this personal-agent key belongs to (confirm with get_agent_identity)."
},
"status": {
"description": "Only return applications currently in this employer-set status.",
"type": "string",
"enum": [
"submitted",
"viewed",
"shortlisted",
"rejected",
"hired",
"withdrawn"
]
},
"limit": {
"description": "Max applications to return (default 20).",
"type": "integer",
"minimum": 1,
"maximum": 50
},
"offset": {
"description": "Pagination offset into the newest-first list.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"account_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Withdraw one of the calling customer account's OWN job applications. The application row is kept and flipped to status=withdrawn (the employer sees an honest withdrawn status; nothing is deleted), and the seeker can re-apply later, which reactivates the same application. Idempotent: withdrawing an already-withdrawn application succeeds and reports already_withdrawn=true — never an error. Only the applicant's own application changes; withdrawing never affects the employer's trust score, ranking, or reviews. Requires a customer personal agent key whose account_id matches the account_id argument (apply_to_job-scoped keys may also withdraw; call get_agent_identity first). Returns job_application_not_found when the application does not belong to this account.
Parameters
| account_id | string | required | The customer account id this personal-agent key belongs to (confirm with get_agent_identity). |
| application_id | string | required | The application to withdraw (from list_my_job_applications or apply_to_job). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The customer account id this personal-agent key belongs to (confirm with get_agent_identity)."
},
"application_id": {
"type": "string",
"minLength": 1,
"description": "The application to withdraw (from list_my_job_applications or apply_to_job)."
}
},
"required": [
"account_id",
"application_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Create, edit, publish, unpublish, or delete a deal/coupon for a business you manage. This mutates deal records: operation=create makes a draft, operation=publish takes a draft live, operation=unpublish cancels public display, operation=update overwrites supplied deal fields, and operation=delete removes the deal. Not idempotent for create/delete/publish transitions. Requires a scoped management key (account_id + business_id matched, allowed_actions include manage_deals) — the management key works on any plan tier (rate-limited per plan; management_rate_limited when the hourly allowance is used up), but the DEALS FEATURE itself stays paid: returns deals_paid_tier_required when the business is on the Free tier; call get_agent_identity first. Never affects the trust score or ranking.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The business this deal belongs to (must be in the key's allowed_business_ids). |
| operation | string | required | |
| deal_id | string | optional | Required for update/publish/unpublish/delete. |
| title | string | optional | |
| description | string | optional | |
| discount_label | string | optional | Human-readable discount, e.g. "20% off" or "$10 off". |
| promo_code | any | optional | |
| terms | any | optional | |
| starts_at | any | optional | ISO date; null/absent = live immediately. |
| ends_at | any | optional | ISO date; null/absent = no expiry. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The business this deal belongs to (must be in the key's allowed_business_ids)."
},
"operation": {
"type": "string",
"enum": [
"create",
"update",
"publish",
"unpublish",
"delete"
]
},
"deal_id": {
"description": "Required for update/publish/unpublish/delete.",
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"discount_label": {
"description": "Human-readable discount, e.g. \"20% off\" or \"$10 off\".",
"type": "string"
},
"promo_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"terms": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"starts_at": {
"description": "ISO date; null/absent = live immediately.",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"ends_at": {
"description": "ISO date; null/absent = no expiry.",
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"account_id",
"business_id",
"operation"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Update editable profile fields for a business you manage: display_name, category, website, phone, city, state, zip. Provide only the fields you want to change; any supplied field replaces/overwrites the current stored value, and repeating the same payload is idempotent. Changing category REQUIRES category_aliases: 1-3 exact taxonomy leaf aliases (discover them via GET /v1/taxonomy/suggest?q=...) — they set the business's authoritative category placement in search. Requires a scoped management key (allowed_actions include update_business_profile) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Cannot edit legal name, verification evidence, billing, publish state, or the trust score.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| display_name | string | optional | |
| category | string | optional | |
| category_aliases | array | optional | Exact taxonomy leaf aliases (1-3) for the business, e.g. home_property.trades.hvac_services. Required when category is supplied. |
| website | string | optional | |
| phone | string | optional | |
| city | string | optional | |
| state | string | optional | |
| zip | string | optional |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"display_name": {
"type": "string"
},
"category": {
"type": "string"
},
"category_aliases": {
"description": "Exact taxonomy leaf aliases (1-3) for the business, e.g. home_property.trades.hvac_services. Required when category is supplied.",
"maxItems": 3,
"type": "array",
"items": {
"type": "string"
}
},
"website": {
"type": "string"
},
"phone": {
"type": "string"
},
"city": {
"type": "string"
},
"state": {
"type": "string"
},
"zip": {
"type": "string"
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Set (or clear) the structured operating hours for a business you manage — the same validated write the owner's dashboard hours editor performs. Supply the WHOLE document each time (idempotent replace): hours.weekly maps every weekday mon..sun to { status, ranges } where status is one of open (1-4 time ranges, split hours like a lunch break supported), closed, open_24 (open 24 hours), or appointment (by appointment only); ranges use business-local 24h "HH:MM" times with open < close (close may be "24:00" = midnight). hours.overrides is an optional list of date-specific SPECIAL/HOLIDAY schedules ({ date: "YYYY-MM-DD", label e.g. "Independence Day", status, ranges }) that REPLACE the weekly schedule on that date. Pass hours=null to clear the schedule (profile shows no hours again). The business's IANA time_zone is derived server-side from its location; the public payloads expose the schedule plus a live computed open_now status in that zone. Hours are informational display data ONLY — they never change trust score, ranking, reach, share-of-voice, or eligibility. Requires a scoped management key (allowed_actions include update_business_profile).
Parameters
| account_id | string | required | |
| business_id | string | required | |
| hours | any | required | The full hours document, or null to clear the stored schedule. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"hours": {
"anyOf": [
{
"type": "object",
"properties": {
"weekly": {
"type": "object",
"properties": {
"mon": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"tue": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"wed": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"thu": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"fri": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"sat": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
},
"sun": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"description": "Required (1-4, non-overlapping) when status=\"open\"; business-local \"HH:MM\".",
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"status"
]
}
},
"required": [
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun"
]
},
"overrides": {
"maxItems": 40,
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "Calendar date \"YYYY-MM-DD\" this override applies to."
},
"label": {
"description": "Shown with the date, e.g. \"Independence Day\".",
"type": "string",
"maxLength": 60
},
"status": {
"type": "string",
"enum": [
"open",
"closed",
"open_24",
"appointment"
]
},
"ranges": {
"maxItems": 4,
"type": "array",
"items": {
"type": "object",
"properties": {
"open": {
"type": "string"
},
"close": {
"type": "string"
}
},
"required": [
"open",
"close"
]
}
}
},
"required": [
"date",
"status"
]
}
}
},
"required": [
"weekly"
]
},
{
"type": "null"
}
],
"description": "The full hours document, or null to clear the stored schedule."
}
},
"required": [
"account_id",
"business_id",
"hours"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Add or remove branding media for a business you manage — all three kinds: kind=business_photo (default) is the tier-capped GALLERY: operation=add uploads one image (JPEG/PNG/WebP base64, up to 8MB) that enters the media review queue before appearing publicly. kind=logo and kind=cover_photo are REPLACE-IN-PLACE SINGLETONS that follow the owner-dashboard path exactly: JPEG/PNG/WebP/SVG up to 5MB, SVG is sanitized on upload, the new file replaces the prior one and is published immediately (moderation is reactive, same as owner uploads). operation=remove deletes any branding photo by asset_id (verification evidence files are never reachable here). Photos never change the trust score, verification, or ranking. Requires a scoped management key (allowed_actions include update_business_photos) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up).
Parameters
| account_id | string | required | |
| business_id | string | required | |
| operation | string | required | |
| kind | string | optional | Branding kind for add (default business_photo = gallery). logo/cover_photo replace the current one in place. |
| file_name | string | optional | Required for add. |
| content_type | string | optional | Image MIME type, required for add. |
| size_bytes | integer | optional | Byte length of the decoded image, required for add. |
| data_base64 | string | optional | Base64-encoded image bytes, required for add. |
| asset_id | string | optional | Required for remove. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"operation": {
"type": "string",
"enum": [
"add",
"remove"
]
},
"kind": {
"description": "Branding kind for add (default business_photo = gallery). logo/cover_photo replace the current one in place.",
"type": "string",
"enum": [
"logo",
"cover_photo",
"business_photo"
]
},
"file_name": {
"description": "Required for add.",
"type": "string"
},
"content_type": {
"description": "Image MIME type, required for add.",
"type": "string"
},
"size_bytes": {
"description": "Byte length of the decoded image, required for add.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"data_base64": {
"description": "Base64-encoded image bytes, required for add.",
"type": "string"
},
"asset_id": {
"description": "Required for remove.",
"type": "string"
}
},
"required": [
"account_id",
"business_id",
"operation"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List inbound customer messages for a business you manage, newest first, each with any replies already sent. Requires a scoped management key (allowed_actions include list_customer_messages) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Use the returned interaction_id with reply_to_customer_message.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| limit | integer | optional | Max messages to return (default 20). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"limit": {
"description": "Max messages to return (default 20).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Post a reply to an inbound customer message on behalf of a business you manage. Pass the interaction_id from list_customer_messages and the reply body. Requires a scoped management key (allowed_actions include reply_to_customer_message) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). The reply is stored and attributed to this agent; it does not change the trust score.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| interaction_id | string | required | The customer message being answered (from list_customer_messages). |
| body | string | required |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"interaction_id": {
"type": "string",
"minLength": 1,
"description": "The customer message being answered (from list_customer_messages)."
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 4000
}
},
"required": [
"account_id",
"business_id",
"interaction_id",
"body"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Read the Loppee support conversation(s) for a business you manage — the owner↔Loppee-support thread, newest first, each with its full message log and status (open/pending/resolved/closed). SCOPED to THIS business only: it never returns the owner's support tickets about their other businesses. Requires a scoped management key (allowed_actions include list_support_messages) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Read-only; pair with send_support_message to reply.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| limit | integer | optional | Max conversations to return (default 20). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"limit": {
"description": "Max conversations to return (default 20).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Post a message to Loppee support on behalf of a business you manage. It appends to the business's one open support thread (reopening a resolved one), or opens a fresh ticket if none is active — the same behavior as the owner sending from the support widget. A closed ticket is never reused; a new one opens instead. The turn is stored as an owner-side message and attributed to this agent in the audit log. SCOPED to THIS business only. Requires a scoped management key (allowed_actions include send_support_message) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Optional subject (≤160 chars) names a new ticket; body ≤4000 chars. Support chat never affects the trust score, ranking, reach, or review weighting.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| body | string | required | |
| subject | string | optional | Subject for a NEW ticket (ignored when appending to an open one). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"subject": {
"description": "Subject for a NEW ticket (ignored when appending to an open one).",
"type": "string",
"maxLength": 160
}
},
"required": [
"account_id",
"business_id",
"body"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List owner notifications for the business this management agent is scoped to. Returns event metadata, summaries, and resource links only; it never includes raw CVs, full message bodies, or applicant PII. Requires allowed_actions include list_notifications.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| unread | boolean | optional | |
| type | string | optional | |
| limit | integer | optional | |
| offset | integer | optional |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"unread": {
"type": "boolean"
},
"type": {
"type": "string",
"enum": [
"customer_message",
"job_application",
"request",
"claim_status",
"review",
"agent_action",
"missed_contact"
]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List captured MISSED CONTACTS for the business this management agent is scoped to. A missed contact is a real, authenticated customer's blocked attempt to reach the business while it could not receive messages. On a PAID plan the rows include the customer's display label and their written message, and the owner can move one into the inbox from the dashboard to reply. On the FREE plan the rows are LOCKED — kind, time, rough distance, and whether a message is waiting, never identity or content — and a Free business cannot operate a management agent at all (agent_management_paid_tier_required), matching the dashboard. Requires a scoped management key whose allowed_actions include list_missed_contacts. Reading missed contacts never affects trust scores, ranking, or reviews.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| limit | integer | optional | |
| offset | integer | optional |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Mark one owner notification as read for the business this management agent is scoped to. Requires allowed_actions include mark_notification_read.
Parameters
| account_id | string | required | |
| business_id | string | required | |
| notification_id | string | required |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1
},
"business_id": {
"type": "string",
"minLength": 1
},
"notification_id": {
"type": "string",
"minLength": 1
}
},
"required": [
"account_id",
"business_id",
"notification_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Publish the business's ONE public response to a customer review of a business you manage. Repeating the call EDITS the existing response in place (idempotent per review — a business never gets a second response slot). The response is public and attributed to this agent. Responding NEVER changes the trust score, the review, its rating, or its weighting — it only adds the business's side of the story under the review. Requires a scoped management key (allowed_actions include respond_to_review) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up); call get_agent_identity first. Returns review_not_found when the review does not belong to this business, and missing_response_body when body is empty.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The reviewed business (must be in the key's allowed_business_ids). |
| review_id | string | required | The review being answered (review ids appear in the business's review notifications and dashboard payload). |
| body | string | required | The public response text (up to 2000 characters, same cap as the owner dashboard). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The reviewed business (must be in the key's allowed_business_ids)."
},
"review_id": {
"type": "string",
"minLength": 1,
"description": "The review being answered (review ids appear in the business's review notifications and dashboard payload)."
},
"body": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "The public response text (up to 2000 characters, same cap as the owner dashboard)."
}
},
"required": [
"account_id",
"business_id",
"review_id",
"body"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Create, edit, publish, pause, close, or delete a job posting for a business you manage (mirrors manage_business_deal). operation=create makes a DRAFT posting (never live directly). operation=publish takes a draft/paused posting live: when this environment has live billing and payment is required, it returns status=checkout_required with a Stripe Checkout url that the HUMAN business owner must open and pay — this tool NEVER completes payment itself; when billing is off, publish activates the posting directly at no charge. operation=update overwrites only the supplied fields (status changes go through publish/pause/close). operation=delete removes the posting (idempotent: deleting a missing posting reports deleted). Payment controls posting eligibility ONLY — it never ranks jobs, never changes the business's trust score, and never changes recommendation order. Employers must be claimed, verified, and published (jobs_verified_business_required otherwise). Seekers are never charged. Requires a scoped management key (allowed_actions include manage_job_posting) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up); call get_agent_identity first. Not idempotent for create/publish/delete transitions.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The employer business (must be in the key's allowed_business_ids). |
| operation | string | required | create makes a DRAFT; publish takes it live (returns checkout_required with a Stripe url for the HUMAN owner when payment is required); pause/close change visibility; delete removes the posting. |
| job_id | string | optional | Required for update/publish/pause/close/delete. |
| title | string | optional | Job title (required for create). |
| description | string | optional | |
| category | string | optional | Free-text category label; defaults to the employer's category. |
| category_alias | string | optional | Exact taxonomy LEAF alias for field/domain search (discover via GET /v1/taxonomy/suggest); defaults to the employer's primary alias. |
| employment_type | string | optional | |
| workplace_type | string | optional | |
| street_address | string | optional | |
| city | string | optional | Defaults to the employer's city for create. |
| state | string | optional | Two-letter US state; defaults to the employer's state for create. |
| postal_code | string | optional | |
| compensation_text | string | optional | Human-readable pay line, e.g. "$25-$30/hr + commission". |
| salary_min | any | optional | |
| salary_max | any | optional | |
| salary_currency | string | optional | |
| salary_period | string | optional | hour, year, or month. |
| skills | array | optional | |
| experience_level | string | optional | |
| benefits | string | optional | |
| schedule | string | optional | |
| total_job_openings | any | optional | |
| direct_apply | boolean | optional | true = seekers apply on Loppee (free for them); false = external apply_url. |
| apply_url | any | optional | |
| contact_email | any | optional |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The employer business (must be in the key's allowed_business_ids)."
},
"operation": {
"type": "string",
"enum": [
"create",
"update",
"publish",
"pause",
"close",
"delete"
],
"description": "create makes a DRAFT; publish takes it live (returns checkout_required with a Stripe url for the HUMAN owner when payment is required); pause/close change visibility; delete removes the posting."
},
"job_id": {
"description": "Required for update/publish/pause/close/delete.",
"type": "string"
},
"title": {
"description": "Job title (required for create).",
"type": "string"
},
"description": {
"type": "string"
},
"category": {
"description": "Free-text category label; defaults to the employer's category.",
"type": "string"
},
"category_alias": {
"description": "Exact taxonomy LEAF alias for field/domain search (discover via GET /v1/taxonomy/suggest); defaults to the employer's primary alias.",
"type": "string"
},
"employment_type": {
"type": "string",
"enum": [
"full_time",
"part_time",
"contract",
"temporary",
"internship",
"seasonal"
]
},
"workplace_type": {
"type": "string",
"enum": [
"on_site",
"hybrid",
"remote"
]
},
"street_address": {
"type": "string"
},
"city": {
"description": "Defaults to the employer's city for create.",
"type": "string"
},
"state": {
"description": "Two-letter US state; defaults to the employer's state for create.",
"type": "string"
},
"postal_code": {
"type": "string"
},
"compensation_text": {
"description": "Human-readable pay line, e.g. \"$25-$30/hr + commission\".",
"type": "string"
},
"salary_min": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
},
"salary_max": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
},
"salary_currency": {
"type": "string"
},
"salary_period": {
"description": "hour, year, or month.",
"type": "string"
},
"skills": {
"type": "array",
"items": {
"type": "string"
}
},
"experience_level": {
"type": "string"
},
"benefits": {
"type": "string"
},
"schedule": {
"type": "string"
},
"total_job_openings": {
"anyOf": [
{
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"direct_apply": {
"description": "true = seekers apply on Loppee (free for them); false = external apply_url.",
"type": "boolean"
},
"apply_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"contact_email": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"account_id",
"business_id",
"operation"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Report a customer review of a business you manage into Loppee's moderation queue for a claimed policy violation (spam, harassment, off_topic, fake, or other). IMPORTANT: reporting NEVER removes the review — the review stays published, moderation is HUMAN and REACTIVE, and a moderator removes a review only for a recorded policy violation, never for being negative. Do not use this tool to suppress honest criticism; use respond_to_review to answer it publicly. Filing a report never changes the trust score, the review's weighting, or ranking. Requires a scoped management key (allowed_actions include report_review) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up); call get_agent_identity first. Reportability rules: only a NEGATIVE review (rating 3 stars and below) can be reported at all — a 4-5 star review returns review_report_not_negative; only ONE report may be open at a time — while a prior report is being reviewed a new one returns review_report_already_open; and a review accepts at most 3 reports in its LIFETIME — past that the call returns review_report_limit_reached. Returns review_not_found when the review does not belong to this business and invalid_report_reason for an unknown category.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The reviewed business (must be in the key's allowed_business_ids). |
| review_id | string | required | The review being reported. |
| reason_category | string | required | Policy-violation category. 'The review is negative' is not a category — negative reviews are never removed for being negative. |
| reason_detail | string | optional | What specifically violates policy (up to 2000 characters). |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The reviewed business (must be in the key's allowed_business_ids)."
},
"review_id": {
"type": "string",
"minLength": 1,
"description": "The review being reported."
},
"reason_category": {
"type": "string",
"enum": [
"spam",
"harassment",
"off_topic",
"fake",
"other"
],
"description": "Policy-violation category. 'The review is negative' is not a category — negative reviews are never removed for being negative."
},
"reason_detail": {
"description": "What specifically violates policy (up to 2000 characters).",
"type": "string",
"maxLength": 2000
}
},
"required": [
"account_id",
"business_id",
"review_id",
"reason_category"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}List applications to the job postings of a business you manage, newest first — the employer side of the hiring pipeline. PII NOTICE: rows include the applicant's name, email, cover note, and (when attached) a SHORT-LIVED signed resume_url (about 5 minutes; re-list to refresh, null if signing fails). This is an explicit owner grant: the business owner must have checked this action when connecting this key (it is never granted by default), and every call is audit-logged. Handle applicant data only for this business's hiring workflow — never republish it or use it beyond hiring. Optional job_id/status filters and offset pagination (limit up to 100, default 25). Requires a scoped management key (allowed_actions include list_job_applications) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Read-only: listing never changes application statuses and never affects trust score or ranking.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The employer business (must be in the key's allowed_business_ids). |
| job_id | string | optional | Only applications to this posting. |
| status | string | optional | Only applications currently in this status. |
| limit | integer | optional | Max applications to return (default 25). |
| offset | integer | optional | Pagination offset into the newest-first list. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The employer business (must be in the key's allowed_business_ids)."
},
"job_id": {
"description": "Only applications to this posting.",
"type": "string"
},
"status": {
"description": "Only applications currently in this status.",
"type": "string",
"enum": [
"submitted",
"viewed",
"shortlisted",
"rejected",
"hired",
"withdrawn"
]
},
"limit": {
"description": "Max applications to return (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"description": "Pagination offset into the newest-first list.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": [
"account_id",
"business_id"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Set the employer-side status of one application to a job posting of a business you manage: submitted, viewed, shortlisted, rejected, or hired. Applicants alone may withdraw — passing 'withdrawn' is rejected (invalid_job_application_status). Idempotent per (application, status): re-setting the same status is a no-op overwrite. The change is visible to the seeker in their applications view and is audit-logged with this agent's attribution. Status changes never affect the business's trust score, ranking, or the applicant's account. Requires a scoped management key (allowed_actions include update_job_application_status — an explicit owner grant, never default) — works on any plan tier including Free (management actions are rate-limited per plan; management_rate_limited when the hourly allowance is used up). Returns job_application_not_found when the application does not belong to this business's postings.
Parameters
| account_id | string | required | The managing agent's account id (from get_agent_identity). |
| business_id | string | required | The employer business (must be in the key's allowed_business_ids). |
| application_id | string | required | The application to update (from list_job_applications). |
| status | string | required | Employer-set status. Applicants alone may withdraw — 'withdrawn' is rejected here. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The managing agent's account id (from get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The employer business (must be in the key's allowed_business_ids)."
},
"application_id": {
"type": "string",
"minLength": 1,
"description": "The application to update (from list_job_applications)."
},
"status": {
"type": "string",
"enum": [
"submitted",
"viewed",
"shortlisted",
"rejected",
"hired"
],
"description": "Employer-set status. Applicants alone may withdraw — 'withdrawn' is rejected here."
}
},
"required": [
"account_id",
"business_id",
"application_id",
"status"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Check a Loppee-issued subscription coupon code against a business you manage and a chosen paid exposure plan, and return the priced result: original_cents, discount_cents, final_cents, plan_name, and whether the discount repeats (duration: once = first payment, forever = every renewal). Read-only — nothing is redeemed, reserved, or counted against the code's limits. Requires a scoped management key whose account_id + business_id match and whose allowed_actions include validate_coupon; call get_agent_identity first. Coupons are issued by Loppee admins to discount the plan PRICE (this is NOT the business's own customer-facing deals — see manage_deal for those). Machine-readable failures match the owner UI exactly: coupon_not_found (invalid code), coupon_inactive, coupon_expired, coupon_wrong_plan (code is scoped to a different plan), coupon_exhausted (total redemption cap reached), coupon_customer_limit (this business already used it), coupon_requires_paid_plan, plus the standard management auth errors (missing_api_key / forbidden_account / management_rate_limited). A coupon changes the subscription PRICE only — it never affects the trust score, rating, verification, ranking, search visibility, reach radius, or share-of-voice, and this tool cannot either.
Parameters
| account_id | string | required | The agent account id this API key belongs to (confirm with get_agent_identity). |
| business_id | string | required | The managed business to apply the coupon for. Must be within this key's allowed_business_ids. |
| code | string | required | The coupon code exactly as issued by the Loppee team. Case- and whitespace-insensitive. |
| tier | string | required | Paid exposure plan to price: nearby=Silver, local=Gold, regional=Platinum, metro=Diamond. |
| period | string | optional | Billing period to price the plan at. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The agent account id this API key belongs to (confirm with get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The managed business to apply the coupon for. Must be within this key's allowed_business_ids."
},
"code": {
"type": "string",
"minLength": 1,
"description": "The coupon code exactly as issued by the Loppee team. Case- and whitespace-insensitive."
},
"tier": {
"type": "string",
"enum": [
"nearby",
"local",
"regional",
"metro"
],
"description": "Paid exposure plan to price: nearby=Silver, local=Gold, regional=Platinum, metro=Diamond."
},
"period": {
"default": "monthly",
"description": "Billing period to price the plan at.",
"type": "string",
"enum": [
"monthly",
"annual"
]
}
},
"required": [
"account_id",
"business_id",
"code",
"tier"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}Redeem a Loppee-issued subscription coupon for a business you manage: runs the exact same validation as validate_coupon, then creates a Stripe Checkout session for the chosen paid plan WITH the discount already applied, and returns its url plus the priced breakdown (original_cents, discount_cents, final_cents) and a redemption_id. IMPORTANT: this tool never charges anyone — the business owner must open the returned url and complete payment on Stripe's hosted page; until then the redemption is 'pending' and is released automatically if the checkout expires. Redeeming counts against the code's redemption limits while pending, so do not call this speculatively — use validate_coupon to check a code. Not idempotent: each call creates a fresh checkout session and replaces the business's previous pending redemption. Requires a scoped management key whose account_id + business_id match and whose allowed_actions include redeem_coupon (owner opt-in), plus configured billing (billing_not_configured otherwise); call get_agent_identity first. Machine-readable failures match the owner UI exactly: coupon_not_found (invalid code), coupon_inactive, coupon_expired, coupon_wrong_plan (code is scoped to a different plan), coupon_exhausted (total redemption cap reached), coupon_customer_limit (this business already used it), coupon_requires_paid_plan, plus the standard management auth errors (missing_api_key / forbidden_account / management_rate_limited). A coupon changes the subscription PRICE only — it never affects the trust score, rating, verification, ranking, search visibility, reach radius, or share-of-voice, and this tool cannot either.
Parameters
| account_id | string | required | The agent account id this API key belongs to (confirm with get_agent_identity). |
| business_id | string | required | The managed business to apply the coupon for. Must be within this key's allowed_business_ids. |
| code | string | required | The coupon code exactly as issued by the Loppee team. Case- and whitespace-insensitive. |
| tier | string | required | Paid exposure plan to price: nearby=Silver, local=Gold, regional=Platinum, metro=Diamond. |
| period | string | optional | Billing period to price the plan at. |
{
"type": "object",
"properties": {
"account_id": {
"type": "string",
"minLength": 1,
"description": "The agent account id this API key belongs to (confirm with get_agent_identity)."
},
"business_id": {
"type": "string",
"minLength": 1,
"description": "The managed business to apply the coupon for. Must be within this key's allowed_business_ids."
},
"code": {
"type": "string",
"minLength": 1,
"description": "The coupon code exactly as issued by the Loppee team. Case- and whitespace-insensitive."
},
"tier": {
"type": "string",
"enum": [
"nearby",
"local",
"regional",
"metro"
],
"description": "Paid exposure plan to price: nearby=Silver, local=Gold, regional=Platinum, metro=Diamond."
},
"period": {
"default": "monthly",
"description": "Billing period to price the plan at.",
"type": "string",
"enum": [
"monthly",
"annual"
]
}
},
"required": [
"account_id",
"business_id",
"code",
"tier"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}README not available yet.
Hosted server - connect over the network, no local install.
https://loppee.com/mcpclaude_desktop_config.json
{
"mcpServers": {
"loppee": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://loppee.com/mcp"
]
}
}
}Desktop config is stdio-only; this bridges via mcp-remote. Native remote: Settings > Connectors.