When to use this endpoint

Use Contract_edit only to reproduce CRM1’s full edit dialog or the legacy CSV importer. It is replacement-oriented: omitted fields are written as blank or zero.

For targeted changes, use the relevant Contract_set* route or the mapped Contract_updateData endpoint.

Authentication and permissions

The request must authenticate as a nonzero user through signed API-key fields or a logged-in CRM session. The handler returns not logged in when no user ID is present.

No page or role-permission check is performed; the update uses the authenticated tenant.

Parameters

ParameterTypeRequiredDescription
idInteger stringYesPositive contract ID. Existence is checked without excluding soft-deleted rows.
nameStringEffectively yesReplacement name. The handler reads it without an existence or length check; omission can become an empty value after a runtime notice.
type_idInteger stringNoReplacement contract-type ID; defaults to 0 and is not validated.
number / address / manager / notesStringsNoReplacement values; each defaults to blank. No schema-length validation is performed.
budgetNumber stringNoConverted with floatval; omitted and nonnumeric values become zero.
not_invoiceableScalarNoStored as the only property in a newly encoded meta object; defaults to numeric 0.
date_startedDate/time stringNoApplied only when strtotime produces an epoch after 2010-01-01; stored as YYYY-MM-DD. Blank/invalid values leave the old date unchanged.
date_completedDate/time stringNoApplied only when parsed after 2010-01-01; stored as a date-time. It cannot be cleared through this route.
expiryYYYY-MM-DD stringNoLegacy input. Shape is checked, but the handler writes a column named expiry rather than the mapped expiry_date and does not check the update result. Use Contract_setExpiryDate.

Example request

$result = FM_api('Contract_edit', [
	'id' => '720',
	'name' => 'North Region Service Contract',
	'type_id' => '8',
	'number' => 'CT-720',
	'address' => 'North Region',
	'manager' => 'Service Desk',
	'budget' => '25000',
	'notes' => 'Renewal review due in September.',
	'not_invoiceable' => '0',
]);

Example response

{
  "ok": 1
}

Errors and unusual responses

ResponseCondition
{"error":"not logged in"}No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs.
{"error":"not logged in"}No authenticated user ID is available.
{"error":"missing or invalid parameter: id"}The ID is absent or not positive.
{"error":"invalid parameter: expiry"}A nonblank legacy expiry value does not match YYYY-MM-DD.
{"error":"Contract does not exist"}No contract row, including deleted rows, has the supplied ID.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • This is a full legacy replacement, not a patch. Missing optional strings become blank and missing numeric values become zero.
  • The endpoint can update a soft-deleted contract and always returns ok after issuing the update, even if the database write fails.
  • When the expiry key is present, the type-104 status worker is replaced using that value; contract email schedules are not synchronized.

Side effects

  • Updates last_edited and invalidates the contracts cache.
  • No contract audit entry, mention notice, or notification-service event is generated by this route.

See it in Fieldmotion

CRM1

Open Contracts, choose Edit on a row, save the dialog, and filter Network requests for Contract_edit. CRM1 sends all replacement fields together.

CRM2

No normal CRM2 caller was found. CRM2 uses mapped Contract_updateData and dedicated delete actions.

Related endpoints