Resources

Custom fields

Custom fields are how a workspace stores its own data on a record: a claim number, a warranty term, a link to the job in another system. When you need to match a Coastline project to a record somewhere else, a custom field is usually the only reliable join, because customer names rarely agree across two systems and addresses get typed differently.

Match on key, not label

label is what a workspace admin sees and can rename whenever they like. key is the slug that stays put. An integration that keys on the label breaks silently the first time somebody fixes a typo in Settings.

GET/v1/opportunities/{id}/custom-fields

List custom fields on a project

Returns every custom field defined for opportunities in the workspace, with this record's value on each. A project is an opportunity whose approval_status is project, so one endpoint covers both.

Fields with no value on the record come back with value: null rather than being omitted, so you can discover which fields exist before any record has filled one in. Requires opportunities.view.

The custom field object

FieldTypeDescription
keystringStable, workspace-unique slug for the field. This is the handle to match on. It does not change when the label is edited.
labelstringDisplay name a workspace admin chose. Editable at any time, so never key your integration on it.
typeenumtext, long_text, number, currency, date, boolean, single_select, multi_select, contact_reference, vendor_reference, url, email, or phone.
valuemixed | nullThe resolved value: a string, number, boolean, or array of strings. Null when the field has no value on this record.
option_idsstring[]Present on select fields only. The stable option ids behind the labels in value.
reference_idstringPresent on reference fields only. The id of the referenced contact or vendor.
PATCH/v1/opportunities/{id}/custom-fields

Set custom field values

The body is a flat object keyed by field key. Only the keys you send are touched: omitting a key leaves it alone, and sending null clears it. Requires opportunities.edit.

A key that does not exist in the workspace is rejected with 400 validation_error rather than ignored, so a typo in your integration surfaces immediately instead of quietly writing nothing.

Value formats on write

Field typeSendNotes
text, long_text, url, email, phonestringSent as a plain string.
number, currencynumberSent as a JSON number.
datestringYYYY-MM-DD.
booleanbooleantrue or false.
single_selectstringThe option id, not the label. Read the field first to get the ids from option_ids.
multi_selectstring[]An array of option ids.
contact_reference, vendor_referencestringThe id of the contact or vendor to reference.

Where else custom fields appear

You rarely need to call this endpoint on its own. A project-linked expenseembeds its project's custom fields on the payload, and every opportunity webhook carries them in data.custom_fields, in this same shape. Both mean a consumer can resolve the join key without a follow-up round trip.