Files
Upload one file
/a/File_upload
Store one uploaded/data-URI file, create its tenant file record, and update supported parent resources’ legacy file-ID lists.
When to use this endpoint
Use File_upload for CRM1’s sequential upload control or API clients sending a data URI. For true multipart upload, Files_upload is the simpler current route.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session and establish the tenant database context.
The handler performs no record-owner or resource-specific permission check. CRM screens may hide the action, but callers with tenant API/session access can target any matching file ID.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
type_id | Integer-compatible | Yes | Linked resource ID. Presence is checked, but zero is accepted. |
type_enum | Integer-compatible | Effectively yes | Linked resource type; absent becomes zero. Common verified values are 0 Customer, 1 Asset Type, 2 Asset, 3 Job, 4 User, 5 recurring Job, 6 User photo, 7 report-design image, 8 Job form photo, 9 report PDF background, 10 private/non-downloadable, 11 form file, 12 Quote, and 13 email-template image. Other modules use later values; use the enum already emitted by the relevant CRM workflow. |
Filedata | Multipart file or data-URI string | Yes | Multipart field when $_FILES is populated, otherwise a data URI. The data-URI branch base64-decodes everything after the first comma without strict validation. |
filename | String | Data-URI branch | Stored display filename. Multipart upload uses the client filename. |
unique | Integer-compatible | No | Truthy makes the successful new upload the only live file for the same type/resource by deleting earlier live files through File_delete. |
Example request
$result = FM_api('File_upload', [
'type_enum' => '2',
'type_id' => '1042',
'filename' => 'asset-photo.jpg',
'Filedata' => 'data:image/jpeg;base64,/9j/4AAQSkZJRg...',
]);
Example response
{
"ok": 1,
"id": 4821,
"url": "files/2/1042/7d4f..."
}
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":"no file uploaded"} | Multipart data exists but its Filedata request value is missing/falsy under the legacy check. |
{"error":"missing or invalid parameter: type_id"} | The type-ID key is absent. |
{"error":"missing parameter: Filedata"} | Neither multipart nor data-URI content is supplied. |
{"error":"file too large. max file size is 12582912 bytes"} | Decoded content exceeds the storage limit. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- The storage URL contains the type, resource ID, and a random MD5 token. The library stores the bytes and inserts metadata containing the uploading user ID.
- Customer, Asset, Job, User, and recurring-Job types update parent file lists/logs inside the storage helper. Customer/Asset lists are then rebuilt again by this endpoint. Job outsourcing propagation may update the linked tenant.
- With
unique=1, previous rows remain as soft-deleted metadata with content removed and deletion-log entries. Filename/content MIME is not validated here; only byte length is enforced.
See it in Fieldmotion
CRM1
Use Upload Files on Customer, Job, Asset, User, Task, recurring-Job, Asset Type, or generic file widgets.
CRM2
Most modern drop zones use Files_upload; some shared support/client code still targets this singular route.
Related endpoints
Files_uploadaccepts multipart input.File_getMaxUploadSizereports the byte limit.