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
| Credential | Looks like | Header | Opens |
|---|---|---|---|
| API key | fondaro_pk_ + 32 letters and digits | Authorization: Bearer <key> | The /v1 routes, /properties/* and /property-sources/*, within its scopes |
| Integration key | fdr_n8n_ + 32 hex characters | Authorization: Bearer <key> | /integrations/v1/*. See Integration reporting |
| MCP key or OAuth token | fdr_mcp_… or fdr_oat_… | Authorization: Bearer <token> | The MCP server only. See MCP server |
| Session token | A signed-in member's session | Authorization: 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.
/v1accepts only newer, server keys. A key made before 4 October 2026 answers403withAPI_KEY_LEGACY, and a key that lists allowed websites answers403withAPI_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
409withAPI_KEY_LIMIT_REACHED; revoke a key you no longer use first. - A key has an owner. A key without one answers
403withAPI_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
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.
| Scope | Allows | Admin only |
|---|---|---|
crm:read | Read your leads, notes, tasks, deals, calendar, calls, conversations, emails, tags and team, and search the CRM | No |
crm:write | Create and update leads, notes, tasks and deals, change statuses and tags, and (admins) assign leads | No |
properties:read | Search and read Fondaro listings, counts, aggregations and themes; read viewings, open houses, collections and buyer requests | No |
properties:write | Create, update, renew and delete your own listings, set their portal publications and generate listing descriptions | Yes |
media:write | Upload listing photos with POST /properties/media/upload | Yes |
sources:read | Browse your connected property sources through /property-sources | No |
brochures:read | Read your brochures and their public links | No |
brochures:write | Create, update, renew, revoke and delete brochures and the listings in them. Creating a brochure, adding or refreshing listings and renewing also need properties:read | No |
documents:read | Read your documents and folders | No |
documents:write | Create Markdown documents, change them, share or stop sharing them, and attach them to leads | No |
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:
The listing and property-source routes keep their own error shape:
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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | Body | string | Yes | 1 to 255 characters |
scopes | Body | string[] | No | Scopes from the table above, no repeats. Omit for the default described above |
allowedOrigins | Body | string[] | No | Up to 20 website origins that may use the key from a browser. Not allowed with a server scope |
expiresInDays | Body | integer | No | 1 to 3650. Omit for a key that does not expire |
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:
POSTandPATCHanswer400withAPI_KEY_ORIGINS_NOT_ALLOWED_FOR_SERVER_SCOPES. - A request that carries an
Originheader (a browser) answers403withAPI_KEY_ORIGIN_NOT_ALLOWED. /v1sends 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.
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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
name | Body | string | No | 1 to 255 characters |
scopes | Body | string[] | No | The full new set. At least one scope, no repeats |
expiresAt | Body | string or null | No | An ISO 8601 date in the future, at most 3650 days from now. null removes the expiry |
allowedOrigins | Body | string[] | No | The full new list. [] removes it |
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
403withAPI_KEY_NOT_YOURS("Only the person this key acts as can remove its website limits"). - A member editing another person's key gets
403withAPI_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.
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.
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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
keyId | Query | UUID | No | An active key; its scopes and origins shape the guide's notes |
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:
| Status | Code | When |
|---|---|---|
401 | UNAUTHENTICATED | On /v1: missing, malformed, unknown, revoked or expired key, or a session token or MCP key. On other routes the 401 has no code |
403 | API_KEY_SCOPE_MISSING | The key lacks the route's scope |
403 | API_KEY_HAS_NO_OWNER | The key has no owner. Create a new key. Rotating an older key does not help |
403 | API_KEY_LEGACY | /v1 refuses keys made before 4 October 2026. Create a new key |
403 | API_KEY_HAS_WEBSITES | /v1 refuses a key that lists allowed websites. Create a key without them |
409 | API_KEY_LIMIT_REACHED | Creating a key would pass 10 active keys for you or 50 for your organization. Revoke one first |
403 | API_KEY_OWNER_NOT_IN_ORGANIZATION | The key's owner left the agency |
403 | API_KEY_ORIGIN_NOT_ALLOWED | A browser request from an origin the key does not list, or from any browser with a server key |
403 | API_KEY_SCOPE_NOT_GRANTABLE | A member asked for properties:write or media:write |
403 | API_KEY_NOT_YOURS | A member changed another person's key, or someone other than the owner widened a key or removed every website from it |
400 | API_KEY_ORIGINS_NOT_ALLOWED_FOR_SERVER_SCOPES | Websites together with a server scope |
400 | API_KEY_UPDATE_EMPTY | PATCH with nothing to change |
400 | API_KEY_EXPIRY_IN_PAST, API_KEY_EXPIRY_TOO_FAR | expiresAt is not in the future, or is more than 3650 days away |
400 | API_KEY_SCOPE_RESERVED | agents:read is reserved and cannot be added |
409 | API_KEY_NOT_ACTIVE, API_KEY_ALREADY_ROTATED | The key cannot be edited or rotated |
404 | The key does not exist, or is set up by Fondaro and cannot be changed | |
429 | Rate 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
lastUsedAtandlastUsedIpfor activity you do not expect.