Skip to content

Custom Fields API

Custom fields allow you to extend Kordon resources with additional attributes specific to your organisation’s needs. All major object types support custom fields: Assets, Business Processes, Controls, Findings, Requirements, Risks, Tasks, and Vendors.

Each custom field has a kind that determines its data type and available configuration options:

KindDisplay nameDescription
stringShort textSingle-line text input
textLong textMulti-line text area
integerNumberWhole number with optional min/max range
booleanYes/NoTrue or false
dateDateDate picker with optional past/future restriction
single_selectSingle selectDropdown with predefined options
multi_selectMulti selectMultiple selection from predefined options
urlLinkURL with optional display text
percentagePercentageNumber in a configurable range (default 0–100)
monetaryCurrencyAmount with a fixed currency
fileFile uploadFile attachment, single or multiple files

The configuration object holds type-specific settings. Most types use an empty {}. Types that accept configuration:

integer

{
"min_value": 0,
"max_value": 1000
}

percentage

{
"min_value": 0,
"max_value": 100
}

date

{
"restriction": "past_only"
}

Accepted values: "past_only", "future_only", or omit the key to allow any date.

single_select and multi_select

Options are managed after creation via the option endpoints. The configuration reflects the current state:

{
"options": [
{ "id": "uuid", "label": "Active", "position": 1 },
{ "id": "uuid", "label": "Inactive", "position": 2 }
]
}

url

{
"allowed_protocols": ["http", "https"]
}

monetary

{
"currency": "EUR"
}

The currency cannot be changed after the field is created.

file

{
"max_file_size_mb": 25,
"allowed_content_types": ["image/*", "application/pdf"],
"allow_multiple": false
}
FieldTypeDescription
is_shown_in_formsbooleanDisplay the field in create and edit forms. Default: false.
is_shown_in_detail_viewbooleanDisplay the field in detail and list views. Default: false.
is_requiredbooleanRequire the field to be filled before saving. Requires is_shown_in_forms: true. Not supported for boolean fields. Default: false.
publicbooleanWhether the field appears in public API responses. Default: true.

Admin and Manager roles can create, update, delete, and reorder custom fields. All authenticated users can read fields and download files attached to file fields.


List all custom fields in your organisation.

Response Fields

FieldTypeDescription
idUUIDUnique identifier for the custom field
namestringInternal field name (lowercase with underscores)
labelstringDisplay name shown to users
descriptionstringOptional description of the field’s purpose
kindstringField type — see field types
attribute_ofstringResource type this field belongs to (e.g. "Asset", "Risk")
field_has_usagebooleanWhether any records currently have a value for this field
is_requiredbooleanWhether the field must be filled in
is_shown_in_formsbooleanWhether the field appears in create/edit forms
is_shown_in_detail_viewbooleanWhether the field appears in detail/list views
publicbooleanWhether the field is visible in public API responses
configurationobjectType-specific settings and options
created_attimestampISO 8601 creation timestamp
updated_attimestampISO 8601 last-updated timestamp
Terminal window
curl --location GET \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/" \
--header "Authorization: Bearer YOUR-TOKEN"

Example Response

Status: 200

{
"data": [
{
"id": "83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f",
"name": "vendor_tier",
"label": "Vendor Tier",
"description": "",
"kind": "single_select",
"attribute_of": "Vendor",
"field_has_usage": true,
"is_required": false,
"is_shown_in_forms": true,
"is_shown_in_detail_view": true,
"public": true,
"configuration": {
"options": [
{ "id": "c1d2e3f4-0000-0000-0000-000000000001", "label": "Gold", "position": 1 },
{ "id": "c1d2e3f4-0000-0000-0000-000000000002", "label": "Silver", "position": 2 }
]
},
"created_at": "2026-02-20T11:19:53+00:00",
"updated_at": "2026-02-20T11:19:53+00:00"
}
],
"meta": {
"total_count": 1,
"page": 1,
"permissions": {
"create": true
}
}
}

Retrieve a specific custom field. The response includes position, permissions, and for select fields, option_usage_counts — a map of option ID to the number of records currently using that option.

Terminal window
curl --location GET \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f" \
--header "Authorization: Bearer YOUR-TOKEN"

Example Response

Status: 200

{
"data": {
"id": "83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f",
"name": "vendor_tier",
"label": "Vendor Tier",
"description": "",
"kind": "single_select",
"attribute_of": "Vendor",
"field_has_usage": true,
"is_required": false,
"is_shown_in_forms": true,
"is_shown_in_detail_view": true,
"public": true,
"configuration": {
"options": [
{ "id": "c1d2e3f4-0000-0000-0000-000000000001", "label": "Gold", "position": 1 },
{ "id": "c1d2e3f4-0000-0000-0000-000000000002", "label": "Silver", "position": 2 }
]
},
"option_usage_counts": {
"c1d2e3f4-0000-0000-0000-000000000001": 42,
"c1d2e3f4-0000-0000-0000-000000000002": 15
},
"position": 1,
"permissions": {
"update": true,
"destroy": true
},
"created_at": "2026-02-20T11:19:53+00:00",
"updated_at": "2026-02-20T11:19:53+00:00"
}
}

Create a new custom field.

FieldTypeRequiredDescription
namestringNoInternal field name (lowercase, underscores only). Auto-generated from label if omitted. Must be unique per resource type.
labelstringYesDisplay name shown to users.
kindstringYesField type — see field types. Cannot be changed once the field has data.
attribute_ofstringYesResource type: Asset, BusinessProcess, Control, Finding, Requirement, Risk, Task, or Vendor.
descriptionstringNoOptional description of the field’s purpose.
is_requiredbooleanNoWhether the field must be filled. Requires is_shown_in_forms: true. Default: false.
is_shown_in_formsbooleanNoDisplay in create/edit forms. Default: false.
is_shown_in_detail_viewbooleanNoDisplay in detail/list views. Default: false.
publicbooleanNoVisible in public API responses. Default: true.
configurationobjectNoType-specific settings — see field configuration.

Example: Creating a single_select field

Terminal window
curl --location POST \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"custom_field": {
"label": "Vendor Tier",
"kind": "single_select",
"attribute_of": "Vendor",
"description": "Classification tier for vendor management",
"is_shown_in_forms": true,
"is_shown_in_detail_view": true
}
}'

Example: Creating a monetary field

Terminal window
curl --location POST \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"custom_field": {
"label": "Contract Value",
"kind": "monetary",
"attribute_of": "Vendor",
"is_shown_in_forms": true,
"configuration": {
"currency": "EUR"
}
}
}'

Example Response

Status: 201

{
"data": {
"id": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890",
"name": "vendor_tier",
"label": "Vendor Tier",
"description": "Classification tier for vendor management",
"kind": "single_select",
"attribute_of": "Vendor",
"field_has_usage": false,
"is_required": false,
"is_shown_in_forms": true,
"is_shown_in_detail_view": true,
"public": true,
"configuration": { "options": [] },
"position": 1,
"permissions": {
"update": true,
"destroy": true
},
"created_at": "2026-06-01T12:30:45+00:00",
"updated_at": "2026-06-01T12:30:45+00:00"
}
}

Update an existing custom field. Only include the fields you want to change.

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"custom_field": {
"label": "Vendor Classification",
"is_required": true,
"is_shown_in_forms": true,
"is_shown_in_detail_view": true
}
}'

Example Response

Status: 200

Returns the full custom field object (same shape as the GET single field response).


Delete a custom field. The field is soft-deleted — it is removed from the API but existing record data is retained internally.

Terminal window
curl --location DELETE \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f" \
--header "Authorization: Bearer YOUR-TOKEN"

Response

Status: 204 No Content


Change the display position of a custom field within its resource type. Position is 1-based and is scoped per attribute_of.

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f/reorder" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"position": 3
}'

Example Response

Status: 200

{
"data": {
"id": "83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f",
"position": 3
}
}

single_select and multi_select fields manage their options through dedicated endpoints. Each option has a UUID, a label, and a position within the field.

Add a new option to a select field.

FieldTypeRequiredDescription
labelstringYesDisplay text for the option
valuestringNoInternal value mapping. Defaults to the label if omitted.
Terminal window
curl --location POST \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f/options" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"option": {
"label": "Gold"
}
}'

Example Response

Status: 201

{
"data": {
"option_id": "c1d2e3f4-0000-0000-0000-000000000001",
"configuration": {
"options": [
{ "id": "c1d2e3f4-0000-0000-0000-000000000001", "label": "Gold", "position": 1 }
]
}
}
}

PATCH /custom_fields/:id/options/:option_id

Section titled “PATCH /custom_fields/:id/options/:option_id”

Rename an existing option. Record values that reference this option are not affected.

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f/options/c1d2e3f4-0000-0000-0000-000000000001" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"option": {
"label": "Platinum"
}
}'

Example Response

Status: 200

{
"data": {
"option_id": "c1d2e3f4-0000-0000-0000-000000000001",
"configuration": {
"options": [
{ "id": "c1d2e3f4-0000-0000-0000-000000000001", "label": "Platinum", "position": 1 },
{ "id": "c1d2e3f4-0000-0000-0000-000000000002", "label": "Silver", "position": 2 }
]
}
}
}

DELETE /custom_fields/:id/options/:option_id

Section titled “DELETE /custom_fields/:id/options/:option_id”

Delete an option. If any records currently use this option, you must supply a replacement_option_id — those records are updated to the replacement. Deleting an option that is in use without a replacement returns a 422 error.

Query Parameters

ParameterTypeDescription
replacement_option_idUUIDRequired when records reference this option. Those records are migrated to the replacement.
Terminal window
curl --location DELETE \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f/options/c1d2e3f4-0000-0000-0000-000000000002?replacement_option_id=c1d2e3f4-0000-0000-0000-000000000001" \
--header "Authorization: Bearer YOUR-TOKEN"

Example Response

Status: 200

{
"data": {
"affected_count": 15,
"async": false,
"configuration": {
"options": [
{ "id": "c1d2e3f4-0000-0000-0000-000000000001", "label": "Gold", "position": 1 }
]
}
}
}

When affected_count is 100 or more, the migration runs as a background job and "async": true is returned. The option is removed from the field immediately; record updates follow asynchronously.

GET /custom_fields/:id/options/:option_id/usage

Section titled “GET /custom_fields/:id/options/:option_id/usage”

Check how many records are currently using a specific option — useful before deleting one.

Terminal window
curl --location GET \
--url "https://YOUR_KORDON_DOMAIN/api/v1/custom_fields/83d028c1-9ce1-4f29-ad2b-994c2d0ebd4f/options/c1d2e3f4-0000-0000-0000-000000000001/usage" \
--header "Authorization: Bearer YOUR-TOKEN"

Example Response

Status: 200

{
"data": {
"option_id": "c1d2e3f4-0000-0000-0000-000000000001",
"usage_count": 42
}
}

For file type fields, files are attached per record. Use these endpoints to retrieve them.

GET /custom_fields/:id/file/:attachment_id

Section titled “GET /custom_fields/:id/file/:attachment_id”

Returns a download URL and filename for a specific attachment.

Example Response

Status: 200

{
"data": {
"url": "/api/v1/custom_fields/83d028c1.../file/att-uuid/download",
"filename": "contract.pdf"
}
}

GET /custom_fields/:id/file/:attachment_id/download

Section titled “GET /custom_fields/:id/file/:attachment_id/download”

Streams the file directly. Accepts an optional disposition query parameter: inline (default) or attachment.


Once a custom field exists, set its value by including the field’s name as a key in a PATCH request to the corresponding resource endpoint.

KindExpected valueExample
stringstring"Acme Corp"
textstring"Multi-line\ntext here"
integerinteger42
booleanbooleantrue
dateISO 8601 date string"2026-12-31"
single_selectoption UUID"c1d2e3f4-0000-0000-0000-000000000001"
multi_selectarray of option UUIDs["c1d2e3f4-...", "c1d2e3f4-..."]
urlobject with url and optional display_text{"url": "https://example.com", "display_text": "Website"}
percentagenumber75.5
monetarynumber12500.00

Example: Setting a single_select value on a Risk

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/risks/RISK_ID" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"risk": {
"risk_category": "c1d2e3f4-0000-0000-0000-000000000001"
}
}'

Example: Setting a url field

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/vendors/VENDOR_ID" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"vendor": {
"contract_link": {
"url": "https://contracts.example.com/vendor-123",
"display_text": "Master Agreement"
}
}
}'

Example: Setting multiple custom fields at once

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/assets/ASSET_ID" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"asset": {
"department": "Engineering",
"replacement_cost": 15000.00,
"last_reviewed": "2026-05-15"
}
}'

Set the field to null to clear it:

Terminal window
curl --location PATCH \
--url "https://YOUR_KORDON_DOMAIN/api/v1/risks/RISK_ID" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer YOUR-TOKEN" \
--data '{
"risk": {
"risk_category": null
}
}'