Felt
DATA · DATA & ANALYTICS
Maps, layers, layer groups, elements, comments, and projects in the workspace they connected.
Acts as the person, not as itself
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Credentials never touch the agent
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Every call on the record
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
felt_delete_maps_by_map_idWRITEDelete map via DELETE /maps/{map_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_maps_by_map_id_comments_by_comment_idWRITEDelete map comment via DELETE /maps/{map_id}/comments/{comment_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_maps_by_map_id_elements_by_element_idWRITEDelete map element via DELETE /maps/{map_id}/elements/{element_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_maps_by_map_id_layer_groups_by_layer_group_idWRITEDelete map layer group via DELETE /maps/{map_id}/layer_groups/{layer_group_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_maps_by_map_id_layers_by_layer_idWRITEDelete map layer via DELETE /maps/{map_id}/layers/{layer_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_maps_by_map_id_layers_by_layer_id_components_by_component_idWRITEDelete layer component via DELETE /maps/{map_id}/layers/{layer_id}/components/{component_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_projects_by_project_idWRITEDelete project via DELETE /projects/{project_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_sources_by_source_idWRITEDelete source via DELETE /sources/{source_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_delete_sources_by_source_id_credentials_by_credential_idWRITEDelete source credential via DELETE /sources/{source_id}/credentials/{credential_id}. Felt answers 204 with no body, so a successful call returns an empty object. DESTRUCTIVE and not reversible through this API: the contract publishes no undelete.
felt_get_libraryREADList library layers via GET /library. Lists library layers. `source` selects whose library: `workspace` (the default), `felt` for the Felt data library, or `all` for both.
felt_get_maps_by_map_idREADShow map via GET /maps/{map_id}.
felt_get_maps_by_map_id_comments_exportREADExport map comments via GET /maps/{map_id}/comments/export. Exports the map's comment threads as an array. `format` selects the export representation; Felt's contract declares the parameter without enumerating its values, so an unrecognised one is answered by Felt rather than refused here.
felt_get_maps_by_map_id_element_groupsREADList map element groups via GET /maps/{map_id}/element_groups.
felt_get_maps_by_map_id_element_groups_by_group_idREADShow map element group via GET /maps/{map_id}/element_groups/{group_id}.
felt_get_maps_by_map_id_elementsREADList map elements via GET /maps/{map_id}/elements.
felt_get_maps_by_map_id_layer_groupsREADList map layer groups via GET /maps/{map_id}/layer_groups.
felt_get_maps_by_map_id_layer_groups_by_layer_group_idREADShow map layer group via GET /maps/{map_id}/layer_groups/{layer_group_id}.
felt_get_maps_by_map_id_layersREADList map layers via GET /maps/{map_id}/layers.
felt_get_maps_by_map_id_layers_by_layer_idREADShow map layer via GET /maps/{map_id}/layers/{layer_id}.
felt_get_maps_by_map_id_layers_by_layer_id_componentsREADList layer components via GET /maps/{map_id}/layers/{layer_id}/components.
felt_get_maps_by_map_id_layers_by_layer_id_components_by_component_idREADShow layer component via GET /maps/{map_id}/layers/{layer_id}/components/{component_id}.
felt_get_maps_by_map_id_layers_by_layer_id_custom_exports_by_export_idREADPoll map layer custom export via GET /maps/{map_id}/layers/{layer_id}/custom_exports/{export_id}. Reads one custom export's current state. This is the poll for the custom-export tool.
felt_get_maps_by_map_id_layers_by_layer_id_get_export_linkREADCreate map layer export link via GET /maps/{map_id}/layers/{layer_id}/get_export_link. Returns a URL (`export_link`) to fetch the layer's data from, not the data itself. The link is Felt's to issue and expire; nothing here follows it, and the connector never follows a redirect.
felt_get_projectsREADList projects via GET /projects.
felt_get_projects_by_project_idREADShow project via GET /projects/{project_id}.
felt_get_sourcesREADList sources via GET /sources.
felt_get_sources_by_source_idREADShow source via GET /sources/{source_id}.
felt_get_userREADShow current user via GET /user. Reports the authenticated Felt user (id, name, email) for the token this connection holds, which is also how a token is checked: Felt's own Authentication page uses this exact call to confirm a token works. It takes no arguments and cannot read another user.
felt_post_duplicate_layersWRITEDuplicate map layers via POST /duplicate_layers. Copies layers or layer groups BETWEEN maps in one call -- each array item names a `source_layer_id` or a `source_layer_group_id` plus a `destination_map_id` -- so this is the one tool whose effect is not confined to a map named in the path. The request body is a JSON ARRAY, one object per item. Whether an item that is OMITTED from the array is left alone or REMOVED is not stated by Felt's contract and was not measurable for this build (no Felt token exists), so send the full intended set and verify with a read before relying on either behaviour.
felt_post_mapsWRITECreate map via POST /maps.
felt_post_maps_by_map_id_add_source_layerWRITEAdd map layer from source via POST /maps/{map_id}/add_source_layer. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
felt_post_maps_by_map_id_comments_by_comment_id_resolveWRITEResolve map comment via POST /maps/{map_id}/comments/{comment_id}/resolve.
felt_post_maps_by_map_id_duplicateWRITEDuplicate map via POST /maps/{map_id}/duplicate. Copies the map and its data into a project or folder you name. The copy is a new map with a new id; nothing about the original changes.
felt_post_maps_by_map_id_element_groupsWRITEUpsert map element groups via POST /maps/{map_id}/element_groups. The request body is a JSON ARRAY, one object per item. Whether an item that is OMITTED from the array is left alone or REMOVED is not stated by Felt's contract and was not measurable for this build (no Felt token exists), so send the full intended set and verify with a read before relying on either behaviour.
felt_post_maps_by_map_id_elementsWRITEUpsert map elements via POST /maps/{map_id}/elements.
felt_post_maps_by_map_id_embed_tokenWRITECreate map embed token via POST /maps/{map_id}/embed_token. Mints a short-lived embed token for ONE named viewer: `user_email` is required, and the response carries `token` plus `expires_at`. The token it returns is a credential for that viewer's browser, so treat the result as secret.
felt_post_maps_by_map_id_image_exportsWRITECreate map image export via POST /maps/{map_id}/image_exports.
felt_post_maps_by_map_id_layer_groupsWRITEUpdate map layer groups via POST /maps/{map_id}/layer_groups. The request body is a JSON ARRAY, one object per item. Whether an item that is OMITTED from the array is left alone or REMOVED is not stated by Felt's contract and was not measurable for this build (no Felt token exists), so send the full intended set and verify with a read before relying on either behaviour.
felt_post_maps_by_map_id_layer_groups_by_layer_group_idWRITEUpdate map layer group via POST /maps/{map_id}/layer_groups/{layer_group_id}.
felt_post_maps_by_map_id_layer_groups_by_layer_group_id_publishWRITEPublish map layer group via POST /maps/{map_id}/layer_groups/{layer_group_id}/publish.
felt_post_maps_by_map_id_layersWRITEUpdate map layer via POST /maps/{map_id}/layers. The request body is a JSON ARRAY, one object per item. Whether an item that is OMITTED from the array is left alone or REMOVED is not stated by Felt's contract and was not measurable for this build (no Felt token exists), so send the full intended set and verify with a read before relying on either behaviour.
felt_post_maps_by_map_id_layers_by_layer_id_componentsWRITECreate layer component via POST /maps/{map_id}/layers/{layer_id}/components.
felt_post_maps_by_map_id_layers_by_layer_id_components_by_component_idWRITEUpdate layer component via POST /maps/{map_id}/layers/{layer_id}/components/{component_id}.
felt_post_maps_by_map_id_layers_by_layer_id_custom_exportWRITECreate map layer custom export via POST /maps/{map_id}/layers/{layer_id}/custom_export. Starts a custom layer export and answers with the export record. Poll it with the custom-export read tool (`felt_get_maps_by_map_id_layers_by_layer_id_custom_exports_by_export_id`); the ledger records no async-job contract, so there is no other completion signal than that read.
felt_post_maps_by_map_id_layers_by_layer_id_publishWRITEPublish map layer via POST /maps/{map_id}/layers/{layer_id}/publish.
felt_post_maps_by_map_id_layers_by_layer_id_refreshWRITERefresh map layer via POST /maps/{map_id}/layers/{layer_id}/refresh. Asks Felt to refresh the layer from its source now. It does not wait: read the layer back to see `last_refreshed_at` move.
felt_post_maps_by_map_id_layers_by_layer_id_update_styleWRITEUpdate map layer style via POST /maps/{map_id}/layers/{layer_id}/update_style.
felt_post_maps_by_map_id_moveWRITEMove map via POST /maps/{map_id}/move. Moves the map to another project OR another folder -- the body is a `oneOf` and exactly one of `project_id` / `folder_id` is sent. Moving a map changes who can see it, because visibility is the project's.
felt_post_maps_by_map_id_updateWRITEUpdate map via POST /maps/{map_id}/update.
felt_post_maps_by_map_id_uploadWRITEUpload map layer via POST /maps/{map_id}/upload. Creates a layer by UPLOAD and answers with the layer plus the presigned upload target Felt expects the file to be PUT to. Agentic Fabriq does not transfer the file: this tool arranges the upload, and the transfer happens against the URL Felt returns.
felt_post_projectsWRITECreate project via POST /projects.
felt_post_projects_by_project_id_updateWRITEUpdate project via POST /projects/{project_id}/update.
felt_post_sourcesWRITECreate source via POST /sources. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
felt_post_sources_by_source_id_credentialsWRITECreate source credential via POST /sources/{source_id}/credentials. Stores a credential FELT will use to reach the customer's own data source (Snowflake, Postgres, BigQuery, an OAuth M2M client ...). The secret in this body is the customer's source credential, not their Felt token, and it is written to Felt rather than read back: Felt's source reads never return it. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
felt_post_sources_by_source_id_credentials_by_credential_id_updateWRITEUpdate source credential via POST /sources/{source_id}/credentials/{credential_id}/update. Replaces a stored source credential. Same warning as creating one: the body carries the customer's own database or OAuth secret. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
felt_post_sources_by_source_id_syncWRITESync source via POST /sources/{source_id}/sync. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
felt_post_sources_by_source_id_updateWRITEUpdate source via POST /sources/{source_id}/update. Felt answers 202 Accepted: the work is QUEUED, not finished, when this call returns. The contract records no async-job resource for it, so read the source or the map's layers back to see the result land.
Often connected alongside
Put Felt behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.