Settings bookmarks
Save a bookmark and favicon
/a/Link_save
Save a bookmark with optional site metadata and favicon discovery
When to use this endpoint
Use for CRM1 Add/Edit Links when the server should attempt to discover a site-root frame hint and icon. The bookmark is committed before optional discovery, so a saved warning must not be retried as a new create.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. All bookmark endpoints require Settings Links View (pageSettingsLinks_view); client administrators pass the standard permission helper. Missing permission fails closed. An API key acts as its associated user.
The authenticated tenant owns the rows. Reads expose userID=0 (shared) and the acting user’s rows, even for admins. Writes to existing rows require ownership unless the actor is a client administrator; non-admins cannot edit/delete shared rows. No bookmark-specific tenant setting, department filter or separate create/edit role is consulted.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Positive integer or zero | No | Omitted, zero or blank means create; positive canonical ID means update an existing editable row. Other invalid values fail. |
name | String | Yes | Trimmed nonblank label; no uniqueness or explicit maximum length. |
url | HTTP(S) URL string | Yes | Trimmed, nonblank, lowercase http:// or https:// prefix with a host. Credentials and whitespace/control characters fail. Internal destinations may be saved, but server discovery is skipped with a saved warning. |
Example request
$saved = FM_api('Link_save', ['name'=>'Operations handbook', 'url'=>'https://example.test/handbook/']);
Example response
{"ok":1,"id":1042}
Optional discovery/storage failure instead adds saved=1 and warning text to the same ok/id reply. This means the bookmark exists; refresh it rather than repeating creation.
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"permission denied"} | Missing page access, non-owned existing write target, or forbidden ownership assignment. |
{"error":"missing or invalid parameter: id/ids"} | Invalid explicit ID selector; absent required selectors can instead report missing or invalid parameter: id. |
{"error":"Bookmark not found or not editable"} | An update target does not exist. |
{"error":"Unable to save bookmark changes. Check the saved state before retrying."} | Failed database/history operation or uncertain commit. Read failures instead return Unable to read bookmarks. |
{"error":"url must begin with http:// or https://"} | URL lacks the case-sensitive lowercase prefix. Missing/blank/invalid name or URL reports missing or invalid parameter: name/url. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Creation uses shared ownership for admins and personal ownership otherwise. Updates retain ownership and require an existing editable ID. Request userID/canBeEmbedded values are ignored. Name and URL validation precedes the login check.
- The initial committed embedding hint is 0. Discovery requests the site root rather than the saved path; a successful response without X-Frame-Options or CSP frame-ancestors permits a stored hint of 1. This remains a hint, not a browser policy guarantee.
- Discovery allows only ports 80/443 and public IP destinations. Every DNS A/AAAA answer must be public; mixed/internal/reserved answers skip fetching. The verified destination is pinned for HTTP requests, proxies are disabled and redirects are not followed. HTTP calls have 2-second connect and 4-second overall limits, a 64 KiB header limit and 256 KiB body limit.
- The root favicon.ico is converted from its first ICO frame to PNG fitting 75×56, with input/output/resource and subprocess-time limits. Conversion uses a unique private temporary directory removed after use; invalid/missing icons produce a warning rather than an empty stored file.
- Row persistence is checked before remote requests. Metadata-hint and fileslib work follows the primary commit and can fail independently. The warning does not undo the bookmark.
- Native request arrays are required where stated; JSON strings are not decoded. No direct mobile app/m-service caller for this Settings-bookmark family was found. Bookmark IDs are unrelated to document share tokens.
Side effects
- Writes tenant links and invalidates its cache. Creation and changed mapped fields receive individual tenant history rows with acting-user attribution; deletion records a deletes audit. Database changes and history are transactional, including a multi-ID batch. A failed read, write or history operation fails the request and rolls back the batch. An uncertain commit is not automatically replayed: refresh before retrying.
- May resolve DNS and perform two bounded root/favicon requests, invoke ImageMagick convert, and replace the icon through fileslib with type_enum=15/type_id=bookmark ID and acting-user attribution. Requires cURL, DNS, ImageMagick/process execution and fileslib for discovery only. No email or share token is created.
See it in Fieldmotion
CRM1
Settings → Links opens pageSettingsLinkEdit. It keeps the dialog on an API error; a positive saved ID closes/reloads the list and displays any saved warning.
CRM2
No production CRM2 caller found. Its mapped editor stores text directly without remote discovery.
Related endpoints
- Link_save performs optional site/icon discovery; Link_createData stores mapped values directly.
- Link_getRequestedDetails returns a bare array; Links_getDataTable returns a table envelope.
- Link_updateData changes multiple fields; Link_updateField changes one.
- Link_delete removes one bookmark; Links_deleteData handles an explicit batch.
- LinkShareable_new creates a bearer document/file URL, a separate workflow.