Authentication

Which credential each part of the Fondaro API takes, and how to create, scope, edit, rotate and revoke the API keys that act as you.

Every request to https://api.fondaro.com carries one credential, and each part of the API accepts only its own kind. For the Fondaro API (CRM, listings, property search, brochures, documents) that is an API key. Give it the fewest scopes that work.

Choose a credential

CredentialLooks likeHeaderOpens
API keyfondaro_pk_ + 32 letters and digitsAuthorization: Bearer <key>The /v1 routes, /properties/* and /property-sources/*, within its scopes
Integration keyfdr_n8n_ + 32 hex charactersAuthorization: Bearer <key>/integrations/v1/*. See Integration reporting
MCP key or OAuth tokenfdr_mcp_… or fdr_oat_…Authorization: Bearer <token>The MCP server only. See MCP server
Session tokenA signed-in member's sessionAuthorization: Bearer <session-token>The routes the Fondaro dashboard and apps use, as that member

A credential sent to routes it does not open returns 401. A session token on /v1 returns 401, and so does an MCP key.

Session tokens are short-lived and belong to one signed-in person. The pages for dashboard features (Calendar, Inbox, Documents and others) document those routes. For automation that runs on its own, use an API key, an integration key or an MCP credential.

An API key acts as you

A key acts as the person who created it. A member's key reaches their own leads and what they can see. An admin's key reaches the whole agency. Fondaro checks the role on every call, so a key never has more access than its person.

  • Scopes narrow it further. A key can do only what its scopes allow, and never more than its person.
  • /v1 accepts only newer, server keys. A key made before 4 October 2026 answers 403 with API_KEY_LEGACY, and a key that lists allowed websites answers 403 with API_KEY_HAS_WEBSITES. Create a new key without websites for /v1. Rotating an older key does not change this: it stays an older key, so make a new one.
  • Keys are limited. Each person can have 10 active keys and each organization 50. Creating one past the limit answers 409 with API_KEY_LIMIT_REACHED; revoke a key you no longer use first.
  • A key has an owner. A key without one answers 403 with API_KEY_HAS_NO_OWNER. Create a new key.
  • If you leave the agency, your keys stop working. On /v1, every key of a leaver stops within 5 minutes. A key created on or after 4 October 2026 (or first created then, before a rotation) also stops on the listing and property-source routes within 5 minutes. Older keys keep working on listings and property search as agency keys, so an admin should revoke them.
  • An admin can revoke any key except those set up by Fondaro, which are listed as such and cannot be changed or revoked from the page. An admin sees each key's owner, including one whose owner left.
  • Listing changes made with a key are recorded in the listing's history as apikey:<key id>.

Send a key

bash
curl https://api.fondaro.com/v1/me \  -H "Authorization: Bearer $FONDARO_API_KEY"

Authorization: Bearer works on every route a key opens. X-API-Key: <key> and Authorization: ApiKey <key> are still accepted. If you send more than one, Authorization: ApiKey and X-API-Key win over Bearer. Keys are never accepted in the query string.

Keys are for servers. If a key must run in a web page, see Keep keys safe.

Scopes

A key can do only what its scopes allow. Each scope needs the person to have that access too.

ScopeAllowsAdmin only
crm:readRead your leads, notes, tasks, deals, calendar, calls, conversations, emails, tags and team, and search the CRMNo
crm:writeCreate and update leads, notes, tasks and deals, change statuses and tags, and (admins) assign leadsNo
properties:readSearch and read Fondaro listings, counts, aggregations and themes; read viewings, open houses, collections and buyer requestsNo
properties:writeCreate, update, renew and delete your own listings, set their portal publications and generate listing descriptionsYes
media:writeUpload listing photos with POST /properties/media/uploadYes
sources:readBrowse your connected property sources through /property-sourcesNo
brochures:readRead your brochures and their public linksNo
brochures:writeCreate, update, renew, revoke and delete brochures and the listings in them. Creating a brochure, adding or refreshing listings and renewing also need properties:readNo
documents:readRead your documents and foldersNo
documents:writeCreate Markdown documents, change them, share or stop sharing them, and attach them to leadsNo

Listings belong to the agency, so only an admin can give a key properties:write or media:write. A key created without scopes holds properties:read and sources:read for a member, and those plus properties:write and media:write for an admin. Keys made before 4 October 2026 keep the access they had.

Older keys and keys created without scopes also carry agents:read. It is reserved: it opens no route and cannot be added to a key. PATCH answers 400 with API_KEY_SCOPE_RESERVED, and POST refuses it as a validation error. It still appears in GET /api-keys and GET /v1/me.

A key without the scope a route needs gets 403. On /v1:

json
{  "error": {    "code": "API_KEY_SCOPE_MISSING",    "message": "This API key is missing the crm:write scope.",    "status": 403,    "details": { "missing": ["crm:write"] }  },  "requestId": "0b6f8f0e-6d2b-4b8a-9f43-5f1c2a7d9e11"}

The listing and property-source routes keep their own error shape:

json
{  "statusCode": 403,  "code": "API_KEY_SCOPE_MISSING",  "message": "This API key is missing the properties:write scope.",  "missingScopes": ["properties:write"],  "requiredScopes": ["properties:write"]}

Every operation in the API reference names its scope in x-required-scopes. In the dashboard's API keys page the same scopes appear as areas with a level: No access, Read, or Read and write.

Create a key

POST /api-keys

Creates a key that acts as you. Any member, with a session token. You can also do it on the API keys page: Settings › Integrations › For developers › API keys.

ParameterInTypeRequiredDescription
nameBodystringYes1 to 255 characters
scopesBodystring[]NoScopes from the table above, no repeats. Omit for the default described above
allowedOriginsBodystring[]NoUp to 20 website origins that may use the key from a browser. Not allowed with a server scope
expiresInDaysBodyintegerNo1 to 3650. Omit for a key that does not expire
bash
curl -X POST https://api.fondaro.com/api-keys \  -H "Authorization: Bearer $SESSION_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "name": "Reporting script",    "scopes": ["crm:read"],    "expiresInDays": 90  }'
json
{  "id": "a1b2c3d4-5678-4abc-9def-123456789abc",  "key": "fondaro_pk_Q7r2Lm9XcV4tB8nK3pW6yZ1aD5sF0gHj",  "prefixHint": "fondaro_pk_Q",  "scopes": ["crm:read"]}

key is shown only in this response. Fondaro stores a hash of it and its first 12 characters (prefixHint). In the dashboard, the default expiry for a new key is 90 days.

A member who asks for properties:write or media:write gets 403 with API_KEY_SCOPE_NOT_GRANTABLE.

Use a key in a web page

crm:*, brochures:* and documents:* are server scopes. A key that holds one is for servers only:

  • It cannot list allowed websites: POST and PATCH answer 400 with API_KEY_ORIGINS_NOT_ALLOWED_FOR_SERVER_SCOPES.
  • A request that carries an Origin header (a browser) answers 403 with API_KEY_ORIGIN_NOT_ALLOWED.
  • /v1 sends no CORS headers, so a browser cannot read its responses anyway.

Anyone can read a key that ships in a web page. A key used in a web page holds properties:read (and sources:read if it searches your sources) only, never properties:write or media:write, and lists the website. An origin is a scheme, host and optional port, such as https://www.youragency.com: no path, no wildcard, and plain http only for localhost. A browser request from an origin the key does not list gets 403 with API_KEY_ORIGIN_NOT_ALLOWED. Requests with no Origin header (your server, a build step, curl) are not origin-checked.

List keys

GET /api-keys

Lists your organization's keys. Any member, with a session token. A member sees every key but can change only their own.

bash
curl https://api.fondaro.com/api-keys \  -H "Authorization: Bearer $SESSION_TOKEN"
json
[  {    "id": "a1b2c3d4-5678-4abc-9def-123456789abc",    "name": "Reporting script",    "status": "active",    "prefixHint": "fondaro_pk_Q",    "legacy": false,    "system": false,    "scopes": ["crm:read"],    "allowedOrigins": [],    "rateLimitPerMinute": null,    "createdById": "user_2abcDEF",    "mine": true,    "ownerState": "member",    "createdAt": "2026-10-04T12:00:00.000Z",    "lastUsedAt": "2026-10-05T09:15:00.000Z",    "lastUsedIp": "203.0.113.7",    "lastUsedUserAgent": "curl/8.7.1",    "usageCount": 247,    "expiresAt": "2027-01-02T12:00:00.000Z",    "rotatedFromId": null,    "graceUntil": null  }]

mine is true for your keys. ownerState is member, left (the owner is no longer in the agency) or unknown (the owner could not be checked). ownerState is also unknown for a revoked, expired or rotated-away key. On a colleague's key, a member sees lastUsedIp and lastUsedUserAgent as null; admins and the key's owner see them. The usage fields can lag by about 30 seconds. legacy: true marks an older key with no prefixHint.

Edit a key

PATCH /api-keys/:id

Changes a key without changing its secret. Send at least one field. The response is the row shown above.

ParameterInTypeRequiredDescription
nameBodystringNo1 to 255 characters
scopesBodystring[]NoThe full new set. At least one scope, no repeats
expiresAtBodystring or nullNoAn ISO 8601 date in the future, at most 3650 days from now. null removes the expiry
allowedOriginsBodystring[]NoThe full new list. [] removes it
bash
curl -X PATCH https://api.fondaro.com/api-keys/a1b2c3d4-5678-4abc-9def-123456789abc \  -H "Authorization: Bearer $SESSION_TOKEN" \  -H "Content-Type: application/json" \  -d '{ "scopes": ["crm:read", "crm:write"], "expiresAt": "2027-06-30T00:00:00.000Z" }'

Who may do what:

  • Narrow, rename, change expiry or websites: the key's owner, or an admin.
  • Give a key more access: only its owner, and only within their role. An admin cannot widen a member's key. A key an admin edits for someone else can be narrowed, not widened.
  • Remove every website from a key: only the key's owner. An admin may narrow the list but not clear it; anyone else gets 403 with API_KEY_NOT_YOURS ("Only the person this key acts as can remove its website limits").
  • A member editing another person's key gets 403 with API_KEY_NOT_YOURS.

A narrowed key loses the scope on its next call. A revoked, expired or rotated key cannot be edited: 409 with API_KEY_NOT_ACTIVE. Edit its replacement instead.

Rotate a key

POST /api-keys/:id/rotate

Issues a new secret with the same name, scopes, allowed origins, rate limit, expiry and owner. The old key keeps working for 24 hours, then returns 401. A member rotates their own keys; an admin any key.

bash
curl -X POST https://api.fondaro.com/api-keys/a1b2c3d4-5678-4abc-9def-123456789abc/rotate \  -H "Authorization: Bearer $SESSION_TOKEN"
json
{  "id": "f0e1d2c3-b4a5-4968-8776-655443322110",  "key": "fondaro_pk_Zk3mN8pQ2rT6vX9yB1cE4gH7jL0oS5uW",  "prefixHint": "fondaro_pk_Z",  "rotatedFromId": "a1b2c3d4-5678-4abc-9def-123456789abc",  "previousKeyValidUntil": "2026-10-06T12:00:00.000Z"}

If the key had no owner, the person who rotates it becomes its owner. A key rotates once: rotate its replacement next time. Rotating a revoked or expired key returns 409 with API_KEY_NOT_ACTIVE; rotating it again returns 409 with API_KEY_ALREADY_ROTATED.

Revoke a key

DELETE /api-keys/:id

Stops the key at once. This cannot be undone. A member revokes their own keys; an admin any key.

bash
curl -X DELETE https://api.fondaro.com/api-keys/a1b2c3d4-5678-4abc-9def-123456789abc \  -H "Authorization: Bearer $SESSION_TOKEN"
json
{ "success": true }

Get the website guide for AI builders

GET /api-keys/integration-guide

Returns, as JSON, a Markdown guide for your organization that an AI site builder can turn into a listings website. It never contains a key: it uses the FONDARO_API_KEY placeholder. Any member, with a session token. See Build with AI.

ParameterInTypeRequiredDescription
keyIdQueryUUIDNoAn active key; its scopes and origins shape the guide's notes
bash
curl "https://api.fondaro.com/api-keys/integration-guide?keyId=a1b2c3d4-5678-4abc-9def-123456789abc" \  -H "Authorization: Bearer $SESSION_TOKEN"
json
{  "markdown": "# Fondaro listings for Your Agency ...",  "fileName": "fondaro-mls-integration.md",  "contractVersion": "v1",  "generatedAt": "2026-10-05T12:00:00.000Z",  "exampleCount": 2}

Use integration keys

Integration keys are created in Settings › Integrations › n8n, or with a session token by an organization admin through POST /integrations/n8n/keys (name, optional scopes, optional expiresInDays from 1 to 3650). GET /integrations/n8n/keys lists them and DELETE /integrations/n8n/keys/:id revokes one. The full key is shown once. They act for the whole agency, not for one person, and allow 120 requests a minute each. Scopes are listed on Integration reporting.

Plan for expiry

A key with an expiry returns 401 after expiresAt. Fondaro emails a reminder about a week before it expires: to the key's owner for a member's key, and to the organization's notification address for an admin's key or one whose owner left. Rotate the key or extend its expiry before then. GET /api-keys shows each key's expiresAt.

Look up a key error

On /v1 an error body is the envelope in Errors and limits. Key and /api-keys errors:

StatusCodeWhen
401UNAUTHENTICATEDOn /v1: missing, malformed, unknown, revoked or expired key, or a session token or MCP key. On other routes the 401 has no code
403API_KEY_SCOPE_MISSINGThe key lacks the route's scope
403API_KEY_HAS_NO_OWNERThe key has no owner. Create a new key. Rotating an older key does not help
403API_KEY_LEGACY/v1 refuses keys made before 4 October 2026. Create a new key
403API_KEY_HAS_WEBSITES/v1 refuses a key that lists allowed websites. Create a key without them
409API_KEY_LIMIT_REACHEDCreating a key would pass 10 active keys for you or 50 for your organization. Revoke one first
403API_KEY_OWNER_NOT_IN_ORGANIZATIONThe key's owner left the agency
403API_KEY_ORIGIN_NOT_ALLOWEDA browser request from an origin the key does not list, or from any browser with a server key
403API_KEY_SCOPE_NOT_GRANTABLEA member asked for properties:write or media:write
403API_KEY_NOT_YOURSA member changed another person's key, or someone other than the owner widened a key or removed every website from it
400API_KEY_ORIGINS_NOT_ALLOWED_FOR_SERVER_SCOPESWebsites together with a server scope
400API_KEY_UPDATE_EMPTYPATCH with nothing to change
400API_KEY_EXPIRY_IN_PAST, API_KEY_EXPIRY_TOO_FARexpiresAt is not in the future, or is more than 3650 days away
400API_KEY_SCOPE_RESERVEDagents:read is reserved and cannot be added
409API_KEY_NOT_ACTIVE, API_KEY_ALREADY_ROTATEDThe key cannot be edited or rotated
404The key does not exist, or is set up by Fondaro and cannot be changed
429Rate limit reached; wait Retry-After seconds

Keep keys safe

  • Keep keys in environment variables or a secrets manager, never in code or a repository.
  • Give each integration its own key with only the scopes it needs.
  • Never put a key with write access, or with Leads and CRM, Brochures or Documents access, in a web page.
  • Set an expiry on short-lived integrations, and revoke keys you no longer use.
  • Watch lastUsedAt and lastUsedIp for activity you do not expect.