The Relm API
A REST API for commercial real estate: search any US property, run a multi-agent Intel Report, build 10-year pro-formas, and read your portfolios — 44 endpoints, every finding traceable to a source.
Base URL & authentication
All requests go to https://api.relm.ai/v1 over HTTPS and authenticate with an API key you create on the API keys page. Pass it as a bearer token:
Authorization: Bearer relm_sk_...Each key has a scope: read (all GET endpoints) or full (adds POST/PUT/DELETE — triggering runs and edits). Keys only authenticate for organizations on a paid plan.
Quickstart
Verify your key by fetching your account:
curl https://api.relm.ai/v1/me \
-H "Authorization: Bearer relm_sk_..."Search a property, then start an Intel Report run and poll it — pick your language (the choice applies to every example on this page):
# 1. Search
curl "https://api.relm.ai/v1/search?q=40+Main+St" \
-H "Authorization: Bearer relm_sk_..."
# 2. Start an Intel Report (returns { run_id })
curl -X POST https://api.relm.ai/v1/deep-research \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"portfolio_id":"...","property_id":"..."}'
# 3. Poll status
curl https://api.relm.ai/v1/deep-research/RUN_ID \
-H "Authorization: Bearer relm_sk_..."API reference
44 endpoints, grouped below. Full request/response schemas are in the /v1/openapi.json spec. List endpoints accept limit / offset and return a total. Path placeholders like PROP_ID are shown in UPPERCASE in the examples.
Account
Identify the key and read your organization’s wallet.
/v1/meReturns the user, organization, role, and scope the API key resolves to. Use it to verify a key works and which org it acts in.
curl https://api.relm.ai/v1/me \
-H "Authorization: Bearer relm_sk_..."/v1/creditsThe org’s credit balance, plan, and whether new Intel Report / pro-forma runs can start right now.
curl https://api.relm.ai/v1/credits \
-H "Authorization: Bearer relm_sk_..."Search & preview
Find properties and pull instant preview data by address.
/v1/searchSearch the org’s properties, portfolios, and uploaded documents. Returns matches with the portfolio_id / property_id you can pass to other endpoints.
Parameters
qquery · required — Search text — an address fragment, portfolio name, or document keywords.
curl "https://api.relm.ai/v1/search?q=40+Main+St" \
-H "Authorization: Bearer relm_sk_..."/v1/properties/previewFetch (or serve cached) preview data — basic info, taxes, area stats — for a US address. Synchronous; 10–30s for a cold address. An address must be previewed before it can be added to a portfolio.
Parameters
addressbody · required — Full street address.force_refreshbody — Bypass the 30-day cache and re-fetch (default false).
curl -X POST https://api.relm.ai/v1/properties/preview \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"address":"40 Main St, Brooklyn, NY 11201"}'/v1/properties/preview/progressReal-time progress steps for an in-flight preview. Poll it alongside the preview call; returns an empty list when nothing is running for the address.
Parameters
addressquery · required — The same address string passed to the preview call.
curl "https://api.relm.ai/v1/properties/preview/progress?address=40+Main+St,+Brooklyn,+NY+11201" \
-H "Authorization: Bearer relm_sk_..."Property data
The complete property record for an address — every field group (ownership, transactions, prices, tax, listing, building, commercial financials). Read-scope keys work. Cached per address, so repeat reads are free; these calls do not spend org credits.
/v1/properties/recordsSuperset of the preview: the entire raw record set for a US address in one non-lossy payload. Use paginate=true for large multifamily towers (the provider returns one record per unit).
Parameters
addressquery · required — Full street address, e.g. "40 Main St, Brooklyn, NY 11201".paginatequery — Paginate up to 500 records/page for towers with per-unit records (default false).refreshquery — Bypass the cache and re-fetch (default false).
curl "https://api.relm.ai/v1/properties/records?address=40+Main+St,+Brooklyn,+NY+11201" \
-H "Authorization: Bearer relm_sk_..."/v1/properties/records/{section}A single curated slice of the record. section ∈ ownership | transactions | prices | tax | listing | building | commercial. Keys the record does not carry are omitted (never invented), so each slice is a faithful subset. Mirrors the get_property_* MCP tools.
Parameters
sectionpath · required — ownership, transactions, prices, tax, listing, building, or commercial.addressquery · required — Full street address.paginatequery — Paginate up to 500 records/page for towers with per-unit records (default false).refreshquery — Bypass the cache and re-fetch (default false).
curl "https://api.relm.ai/v1/properties/records/ownership?address=40+Main+St,+Brooklyn,+NY+11201" \
-H "Authorization: Bearer relm_sk_..."Public records
Raw public-record reads, returned in the publisher’s own shape: NYC building records, New York rent registration, hazard and environmental screens, geography, parcels, and tenant credit. Every call answers 200; each block carries its own status, and "timeout" or "error" means that source could not be checked — never that nothing was found. Read-scope keys work; no org credits. Mirrored by the Public records MCP tools.
/v1/data/nycPublic records for one New York City tax lot: lot facts, deeds and parties, housing and building violations, permits, building filings (facades, boilers, elevators, certificates of occupancy, safety violations), hearings, tax liens, sales, rodent inspections, energy benchmarking and more. Omit datasets for a useful default set; datasets=all returns everything but takes over a minute. Each dataset block carries its own records and count, or an error marker. fdny_bfp is a summary the city stopped updating in 2019.
Parameters
bblquery · required — 10-digit borough-block-lot, e.g. 1008350041.datasetsquery — Comma-separated dataset names, or "all". Default: pluto, acris_deeds, hpd_violations, dob_violations, oath. Also: acris_parties, affordable_housing, boiler_permits, bsa_applications, dob_electrical, dob_now_boiler, dob_now_build, dob_now_co, dob_now_elevator, dob_now_facades, dob_now_safety_violations, dob_permits, dohmh_rodent, fdny_bfp, hpd_registration, ll84_benchmarking, rolling_sales, tax_liens.
curl "https://api.relm.ai/v1/data/nyc?bbl=1008350041&datasets=dob_violations,dob_permits,dob_now_co" \
-H "Authorization: Bearer relm_sk_..."/v1/data/dhcrWhether a New York building is registered with the state as rent-regulated. A hit means it registered at least once since 1984, not that its units are regulated today, and there is no unit count. Takes about 15 seconds.
Parameters
house_numberquery · required — House number, e.g. 195.street_namequery · required — Street name without its type, e.g. STANTON.countyquery — County, e.g. NEW YORK. Strongly recommended: street names repeat across boroughs.
curl "https://api.relm.ai/v1/data/dhcr?house_number=195&street_name=STANTON&county=NEW+YORK" \
-H "Authorization: Bearer relm_sk_..."/v1/data/environmentalFederally regulated facilities near a point (compliance, facility registry, hazardous waste, and toxic release records), plus state remediation sites in New York. Outside New York the state block is empty — a coverage fact, not a clean site. For the compliance block, compare count with reported_rows before trusting a total.
Parameters
latquery · required — Latitude (WGS84).lonquery · required — Longitude (WGS84).radius_milesquery — Search radius, up to 5 (default 0.5). Larger radii get slow and noisy.
curl "https://api.relm.ai/v1/data/environmental?lat=40.7128&lon=-74.006&radius_miles=0.5" \
-H "Authorization: Bearer relm_sk_..."/v1/data/hazardsFlood zone, seismic design values, wildfire (wildland–urban interface), and subsidence at a point. Each block has a status; "error" means the screen could not run, never low risk.
Parameters
latquery · required — Latitude (WGS84).lonquery · required — Longitude (WGS84).
curl "https://api.relm.ai/v1/data/hazards?lat=40.7128&lon=-74.006" \
-H "Authorization: Bearer relm_sk_..."/v1/data/geocodeA US street address to its matched address and coordinates. Returns success: false with a reason when there is no match — never a guessed nearby point.
Parameters
addressquery · required — Full street address, e.g. "350 5th Ave, New York, NY 10118".
curl "https://api.relm.ai/v1/data/geocode?address=350+5th+Ave,+New+York,+NY+10118" \
-H "Authorization: Bearer relm_sk_..."/v1/data/countyCounty identity and boundary metadata for a 5-digit county FIPS code.
Parameters
fipsquery · required — 5-digit county FIPS, e.g. 36061 (New York County).
curl "https://api.relm.ai/v1/data/county?fips=36061" \
-H "Authorization: Bearer relm_sk_..."/v1/data/parcelParcel attributes from the county’s own GIS service, by assessor parcel number. Coverage comes from a hand-verified registry — today St. Louis County, MO (29189). Other counties return null fields plus a county_gis_operator_fetch_required flag, meaning "not covered yet", not "no parcel".
Parameters
apnquery · required — Assessor parcel number.county_fipsquery · required — 5-digit county FIPS.statequery — Two-letter state code, e.g. MO.
curl "https://api.relm.ai/v1/data/parcel?apn=09G220112&county_fips=29189&state=MO" \
-H "Authorization: Bearer relm_sk_..."/v1/data/wetlandsMapped wetland features inside a bounding box. count_only=true (the default) is cheap; geometry is not. Can take 8–20 seconds.
Parameters
bboxquery · required — min_lon,min_lat,max_lon,max_lat in WGS84.count_onlyquery — Return only the feature count (default true).
curl "https://api.relm.ai/v1/data/wetlands?bbox=-85.7,42.1,-85.4,42.4&count_only=true" \
-H "Authorization: Bearer relm_sk_..."/v1/data/protected-landsWhether a point sits inside protected land, and who manages it. protected is a real boolean only when status is "success"; on "error" it is null, because "could not check" must not read as "unencumbered". areas is a list, since designations overlap.
Parameters
latquery · required — Latitude (WGS84).lonquery · required — Longitude (WGS84).
curl "https://api.relm.ai/v1/data/protected-lands?lat=37.7456&lon=-119.5936" \
-H "Authorization: Bearer relm_sk_..."/v1/data/tenant-creditPublic-company filing lookup for a tenant or guarantor, by the name on the lease. A miss means "not found in public-company filings", never "not a public company" — subsidiaries, d/b/a names, and franchisees often miss.
Parameters
companyquery · required — Tenant or guarantor name, e.g. "Starbucks Corporation".
curl "https://api.relm.ai/v1/data/tenant-credit?company=Starbucks+Corporation" \
-H "Authorization: Bearer relm_sk_..."/v1/data/street-viewWhether street-level imagery exists at a point, and when it was captured. Metadata only — no image. A capture older than the last sale is a caveat, not evidence.
Parameters
latquery · required — Latitude (WGS84).lonquery · required — Longitude (WGS84).
curl "https://api.relm.ai/v1/data/street-view?lat=40.7484&lon=-73.9857" \
-H "Authorization: Bearer relm_sk_..."Portfolios
Group properties into portfolios and manage membership.
/v1/portfoliosEvery portfolio in the org, newest first. Paginated; the response includes count, total, limit, and offset.
Parameters
limitquery — Max to return (1–200, default 50).offsetquery — Rows to skip (default 0).
curl "https://api.relm.ai/v1/portfolios?limit=50&offset=0" \
-H "Authorization: Bearer relm_sk_..."/v1/portfoliosCreates a new portfolio in the org and returns it (201).
Parameters
namebody · required — Display name (1–200 chars).
curl -X POST https://api.relm.ai/v1/portfolios \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"name":"Brooklyn Multifamily 2026"}'/v1/portfolios/{portfolio_id}One portfolio’s metadata (name, property count, created date). 404 for unknown or cross-org ids.
Parameters
portfolio_idpath · required — Portfolio id.
curl https://api.relm.ai/v1/portfolios/PORTFOLIO_ID \
-H "Authorization: Bearer relm_sk_..."/v1/portfolios/{portfolio_id}/propertiesSummary rows (id, address, section-completion) for the properties in one portfolio. Paginated.
Parameters
portfolio_idpath · required — Portfolio id.limitquery — Max to return (1–200, default 50).offsetquery — Rows to skip (default 0).
curl "https://api.relm.ai/v1/portfolios/PORTFOLIO_ID/properties?limit=50&offset=0" \
-H "Authorization: Bearer relm_sk_..."/v1/portfolios/{portfolio_id}/propertiesAdds a previously-previewed address to the portfolio and returns the new property_id. 404 if the address was never previewed.
Parameters
portfolio_idpath · required — Target portfolio id.addressbody · required — The exact address that was previewed.
curl -X POST https://api.relm.ai/v1/portfolios/PORTFOLIO_ID/properties \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"address":"40 Main St, Brooklyn, NY 11201"}'/v1/portfolios/{portfolio_id}/properties/{prop_id}The full, normalized property data document as it sits in that portfolio.
Parameters
portfolio_idpath · required — Portfolio id.prop_idpath · required — Property id.
curl https://api.relm.ai/v1/portfolios/PORTFOLIO_ID/properties/PROP_ID \
-H "Authorization: Bearer relm_sk_..."/v1/portfolios/{portfolio_id}/properties/{prop_id}Removes a property from a portfolio (org-scoped). 404 if it isn’t in that portfolio.
Parameters
portfolio_idpath · required — Portfolio id.prop_idpath · required — Property id.
curl -X DELETE https://api.relm.ai/v1/portfolios/PORTFOLIO_ID/properties/PROP_ID \
-H "Authorization: Bearer relm_sk_..."Properties
Read properties org-wide or by id, without walking portfolios.
/v1/propertiesEvery property in the org (one row per portfolio membership), newest first. Paginated; optionally scoped to a portfolio.
Parameters
portfolio_idquery — Restrict to a single portfolio.limitquery — Max to return (1–200, default 50).offsetquery — Rows to skip (default 0).
curl "https://api.relm.ai/v1/properties?limit=50&offset=0" \
-H "Authorization: Bearer relm_sk_..."/v1/properties/{prop_id}The full property data document by property id alone (any portfolio in the org). 404 if not in your org.
Parameters
prop_idpath · required — Property id.
curl https://api.relm.ai/v1/properties/PROP_ID \
-H "Authorization: Bearer relm_sk_..."Intel Report
Kick off multi-agent research and follow it to completion.
/v1/deep-researchStarts (or queues) an Intel Report run. A full run (services omitted or ["all"]) researches basics, units, comps, taxes, POIs, area stats, and a summary. It is charged when it completes, by the data and AI work it delivered — about 150 credits for a typical full analysis. Returns a run_id (202); 402 `credit_limit_reached` when the org has no credits left.
Parameters
portfolio_idbody · required — Portfolio containing the property.property_idbody · required — Property to research.servicesbody — Sections to run; omit for a full run. e.g. ["comps","taxes"].auto_run_financialsbody — Start the pro-forma automatically on completion (default false).
curl -X POST https://api.relm.ai/v1/deep-research \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"portfolio_id":"PORTFOLIO_ID","property_id":"PROP_ID"}'/v1/deep-research/{run_id}Per-section statuses plus a rollup: processing | complete | error | stopped. Works for Intel Report and pro-forma runs. Status expires ~24h after completion.
Parameters
run_idpath · required — run_id returned when the run started.
curl https://api.relm.ai/v1/deep-research/RUN_ID \
-H "Authorization: Bearer relm_sk_..."/v1/runs/{run_id}/stepsThe run’s thinking steps (the live activity trace). Pass the returned next_cursor back to receive only new steps. Steps expire ~1h after the run ends.
Parameters
run_idpath · required — Run to inspect.cursorquery — Opaque cursor from a previous response.
curl "https://api.relm.ai/v1/runs/RUN_ID/steps" \
-H "Authorization: Bearer relm_sk_..."/v1/runs/{run_id}/steps/streamThe same steps as a Server-Sent Events stream. Emits a final run_complete event when the run reaches a terminal state; capped per key. Reconnect or fall back to polling on idle/timeout.
Parameters
run_idpath · required — Run to stream.
curl -N https://api.relm.ai/v1/runs/RUN_ID/steps/stream \
-H "Authorization: Bearer relm_sk_..."Pro forma
Build, read, edit, and export the 10-year financial model.
/v1/properties/{prop_id}/proformaStarts the financial pro-forma run (~18 line-item agents; 10–30 min). Returns a run_id (202); 402 `pro_forma_limit_reached` without an active subscription. An Intel Report should have completed first.
Parameters
prop_idpath · required — Property to underwrite.portfolio_idbody · required — Portfolio containing the property.
curl -X POST https://api.relm.ai/v1/properties/PROP_ID/proforma \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"portfolio_id":"PORTFOLIO_ID"}'/v1/properties/{prop_id}/proformaThe transformed pro-forma: Year-1 summary, 10-year projections, and line items. Each line item carries key / label / category / year1_value / per_unit / per_sqft / ten_year_values.
Parameters
prop_idpath · required — Property id.
curl https://api.relm.ai/v1/properties/PROP_ID/proforma \
-H "Authorization: Bearer relm_sk_..."/v1/properties/{prop_id}/proforma/exportDownload the pro-forma as an Excel model (formulas), a formatted PDF report, or raw JSON.
Parameters
prop_idpath · required — Property id.formatquery — xlsx (default) | pdf | json.
curl "https://api.relm.ai/v1/properties/PROP_ID/proforma/export?format=xlsx" \
-H "Authorization: Bearer relm_sk_..." \
-o proforma.xlsx/v1/properties/{prop_id}/financialsSave an edited pro-forma: the full line-item array (same shape GET .../proforma returns) plus optional financing assumptions. Edits are recorded as source="api". Expenses/losses are stored as negative numbers.
Parameters
prop_idpath · required — Property id.portfolio_idbody · required — Portfolio containing the property.line_itemsbody · required — Full FinancialLineItem array.financingbody — purchase_price, down_payment_pct, interest_rate, loan_term_years, closing_costs_pct, plus optional loan structure: interest_only_years (default 0), amortization_years (default = loan_term_years), origination_fee_pct (fraction of the loan, default 0).
curl -X PUT https://api.relm.ai/v1/properties/PROP_ID/financials \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{"portfolio_id":"PORTFOLIO_ID","line_items":[{"key":"gross_potential_income","year1_value":250000}]}'Sections
Read (and, where allowed, write) one section of a property.
/v1/properties/{prop_id}/sections/{section}One data section of a property. Readable: basic_info, taxes, comps, units, summary, area_stats, pois, market, neighborhood_news. (Financials live under the /proforma endpoints.)
Parameters
prop_idpath · required — Property id.sectionpath · required — Section name (see list above).
curl https://api.relm.ai/v1/properties/PROP_ID/sections/taxes \
-H "Authorization: Bearer relm_sk_..."/v1/properties/{prop_id}/sections/{section}Save one section (schema-validated). Writable sections: basic_info, taxes, comps, units, summary, area_stats, pois. 409 if another editor holds the lock; 422 on schema failure. (market and neighborhood_news are read-only.)
Parameters
prop_idpath · required — Property id.sectionpath · required — Writable section name.(body)body · required — The section payload (shape matches what GET returns).
curl -X PUT https://api.relm.ai/v1/properties/PROP_ID/sections/summary \
-H "Authorization: Bearer relm_sk_..." \
-H "Content-Type: application/json" \
-d '{ "...section fields..." }'Documents
Attach deal documents and make them searchable.
/v1/properties/{prop_id}/documentsUpload one or more files (multipart/form-data field "files"). Allowed: pdf, csv, tsv, xlsx, xls, html, json, txt, md, doc, docx, and common images. 50MB per file; per-file failures are reported without failing the batch.
Parameters
prop_idpath · required — Property to attach to.filesbody · required — Multipart form field; repeat for multiple files.
curl -X POST https://api.relm.ai/v1/properties/PROP_ID/documents \
-H "Authorization: Bearer relm_sk_..." \
-F "files=@rent_roll.pdf"/v1/properties/{prop_id}/documents/{document_id}/indexStart vector indexing so a document becomes searchable / citable in chat and an Intel Report (async, 202). Returns an upload_id to poll.
Parameters
prop_idpath · required — Property id.document_idpath · required — Document id from the upload response.
curl -X POST https://api.relm.ai/v1/properties/PROP_ID/documents/DOCUMENT_ID/index \
-H "Authorization: Bearer relm_sk_..."/v1/properties/{prop_id}/documents/indexing-status/{upload_id}Status of an indexing job: pending, in_progress, failed, or complete.
Parameters
prop_idpath · required — Property id.upload_idpath · required — upload_id from the index call.
curl https://api.relm.ai/v1/properties/PROP_ID/documents/indexing-status/UPLOAD_ID \
-H "Authorization: Bearer relm_sk_..."/v1/documents/searchSemantic (vector) search across your org’s uploaded documents. Scope to one property (prop_id), one portfolio (portfolio_id), or neither to search the whole org and find similar content anywhere. Each hit returns the matched text snippet, file name, doc type, property/portfolio, and similarity distance.
Parameters
qquery · required — Natural-language query to match document content.portfolio_idquery — Restrict to documents of one portfolio’s properties.prop_idquery — Restrict to one property’s documents.doc_typequery — Filter by document type (e.g. rent_roll, inspection).top_kquery — Max results (1–50, default 10).
curl "https://api.relm.ai/v1/documents/search?q=roof+replacement&portfolio_id=PORTFOLIO_ID" \
-H "Authorization: Bearer relm_sk_..."Chats
Read your Relm AI chats — org-shared and your private ones.
/v1/chatsYour chats across the org: shared "edit" chats visible to the whole org plus your own private "research" chats, newest first. Returns concise summaries (id, property/portfolio, title, type, message_count) — no message bodies. Filter by portfolio_id, prop_id, or chat_type; paginated.
Parameters
portfolio_idquery — Restrict to chats about one portfolio.prop_idquery — Restrict to chats about one property.chat_typequery — "edit" (org-shared) or "research" (your private) only.limitquery — Max to return (1–200, default 50).offsetquery — Rows to skip (default 0).
curl "https://api.relm.ai/v1/chats?chat_type=research&limit=20" \
-H "Authorization: Bearer relm_sk_..."/v1/chats/{chat_id}Metadata for one chat you can see (property/portfolio, title, type, message_count). 404 for unknown or not-visible chats.
Parameters
chat_idpath · required — Chat id.
curl https://api.relm.ai/v1/chats/CHAT_ID \
-H "Authorization: Bearer relm_sk_..."/v1/chats/{chat_id}/messagesThe chat transcript, paginated by message index (offset). Each message carries its text, sender type (human/agent), sender name, and timestamp. 404 if the chat isn’t visible to you.
Parameters
chat_idpath · required — Chat id.limitquery — Max messages (1–500, default 100).offsetquery — Message index to start from (default 0).
curl "https://api.relm.ai/v1/chats/CHAT_ID/messages?limit=100&offset=0" \
-H "Authorization: Bearer relm_sk_..."Errors & rate limits
Errors use a consistent envelope (5xx responses stay generic):
{ "detail": { "error": "insufficient_scope", "message": "..." } }Branch on error, never on message — the wording is plan-aware and changes without notice. A billing refusal carries reason as well, which is where the subscription cases below are named.
| Status | Code | When |
|---|---|---|
| 401 | invalid_api_key | The key is missing, malformed, revoked, expired, or not one we issued. These are deliberately indistinguishable — there is no separate revoked or expired code. |
| 402 | credit_limit_reached | Starting an Intel Report with no credits left on the org. |
| 402 | pro_forma_limit_reached | Starting a pro-forma without an active subscription. |
| 402 | insufficient_credits | The pre-run credit gate refused the spend before any work began. |
| 402 | reason: subscription_ended | The subscription is over. An ended trial is this refusal with subscription_status: trial_expired alongside it — not a code of its own. |
| 403 | insufficient_scope | A read-scope key on a write verb (anything but GET / HEAD / OPTIONS). |
| 403 | plan_ineligible | The org’s plan is not eligible for API access, so no key can authenticate. |
| 403 | demo_property_read_only | A write against a demo property, which is permanently read-only. |
| 403 | demo_portfolio_read_only | A write against the demo portfolio itself — adding, renaming, or removing. |
| 403 | demo_action_disabled | Starting an Intel Report or a pro-forma on a demo property. |
| 404 | — | No such record, or it belongs to an org this key does not act in. |
| 422 | — | The request body or query failed schema validation. |
| 429 | rate_limit_exceeded | Over the per-key or per-org rate limit. Honour the Retry-After header. |
Over the rate limit you get 429 with a Retry-After header; retry after that many seconds. 5xx responses stay generic.
Over MCP the same refusals come back as the tool’s text result rather than as a transport error, formatted <code>: <message> — so the code survives and a failed tool call is readable by the agent. The one difference is the rate limit, which reports rate_limited there and rate_limit_exceeded over REST.
MCP server
Prefer to drive the API from an AI agent? Connect the Relm MCP server (https://api.relm.ai/mcp/) to Cursor, Claude, or any MCP client. The MCP guide has the setup config and a description of every tool.
Keys are scoped and revocable, calls are rate limited and isolated to your organization, and every research finding is traceable to its source. Your data is never used to train models without your consent.
Build on Relm
Start a subscription, mint an API key, and make your first request in minutes.