> For the complete documentation index, see [llms.txt](https://support.attackforge.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://support.attackforge.com/app/getting-started/custom-fields-and-forms.md).

# Custom Fields and Forms

## Overview <a href="#overview" id="overview"></a>

Every organisation captures information a little differently. Custom fields and forms let administrators add the fields that matter to their organisation and customers, without waiting for product changes. Custom fields work across the application, in reports, and through the Self-Service APIs and MCP tools.

An administrator chooses one of 13 field types, and sets its key, hide condition and access controls. The field then appears in forms, tables and reports, in the APIs, Flows and Events, and in the MCP tools used by AI assistants and agents.

<figure><img src="https://372186556-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M8s1QY2Q6YTHB4a6DMu%2Fuploads%2FNUtRSBPV6lF3pGuftwJA%2Fcustom-fields-at-a-glance.svg?alt=media&amp;token=b9c1a2f8-d41c-411b-9ba2-400fe54b3a15" alt=""><figcaption></figcaption></figure>

## Why use custom fields <a href="#why-use-custom-fields" id="why-use-custom-fields"></a>

* **Capture what your process needs.** Add fields for things like a change ticket number, business unit, data classification or compliance scope.
* **Better reports.** Custom fields can appear in reports, so reports include the details your customers expect.
* **Cleaner data for automation.** Structured fields are easy to filter, report on and use in Flows, Events, APIs and AI and agentic integrations.
* **Simpler forms.** Hide conditions only show a field when it's relevant, so forms stay short.
* **The right people see the right data.** Access controls decide who can view and edit each field.

## Where you can add custom fields <a href="#where-you-can-add-custom-fields" id="where-you-can-add-custom-fields"></a>

Project requests, projects, writeups, vulnerabilities, assets, portfolios, test cases, project test cases, retesting rounds, reporting, project pages, groups and users. You can group fields into **sections** within a form.

Only **Administrators** can set up custom fields. They do this in the **Administration** module.

## Who benefits <a href="#who-benefits" id="who-benefits"></a>

| Who                                  | How                                                                              |
| ------------------------------------ | -------------------------------------------------------------------------------- |
| **Administrators**                   | Shape AttackForge to fit the organisation's process                              |
| **Testers and project coordinators** | Capture the details each engagement needs, in the right place                    |
| **Clients and requestors**           | Provide the right information up front, in a form that only asks what's relevant |
| **Report authors**                   | Pull custom details straight into reports                                        |
| **Integration engineers**            | Read and write structured data through APIs, Flows, Events and MCP tools         |

## Create a custom field <a href="#create-a-custom-field" id="create-a-custom-field"></a>

1. Go to **Administration**, and open the area the field belongs to, such as **Projects** or **Projects > Vulnerabilities**. See "Where custom fields appear" below for every path.
2. Click **Add Custom Field**.
3. Choose the field type.
4. Fill in the field's options, such as its key, label and access controls.
5. Optionally, add it to a section, and set a hide condition.
6. Save the field.

<figure><img src="https://372186556-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M8s1QY2Q6YTHB4a6DMu%2Fuploads%2FleVZdAki8XHvrTwe92E9%2FScreenshot%202026-11-04%20at%204.37.51%E2%80%AFpm.png?alt=media&amp;token=86b477df-8cde-4f05-9cac-4e320d2c2cb4" alt=""><figcaption></figcaption></figure>

### Field options <a href="#field-options" id="field-options"></a>

Most field types share these options:

| Option                | What it does                                                                                                                                                                                 |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Key**               | A unique name for the field, made of letters, numbers and underscores. Use it to refer to the field in the JSON export, ReportGen and the Self-Service APIs.                                 |
| **Placeholder Value** | The default value shown in forms                                                                                                                                                             |
| **Suggested Value**   | An AFScript script that suggests a value, which the user can accept. It can use everything in the form, and runs again each time the form changes. See "Suggest values with AFScript" below. |
| **Label**             | The field's name, shown in forms and data tables                                                                                                                                             |
| **Info**              | A message shown when someone selects the field or enters data into it                                                                                                                        |
| **Required**          | Whether the field must be filled in                                                                                                                                                          |
| **Display in Tables** | Whether the field appears as a column in the relevant tables                                                                                                                                 |
| **Hide Condition**    | A condition that hides the field until it's met. See "Show fields only when they're relevant" below.                                                                                         |
| **Access Controls**   | Which roles, groups or users can view or edit the field and its data                                                                                                                         |

Select and multi-select fields also have:

| Option                    | What it does                                                                                                                                                          |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Add Select Option**     | Adds an option to the menu. There must be at least one. Each option has an **Option** (the text shown in the menu) and a **Value** (the data saved when it's chosen). |
| **Default Select Option** | The option already chosen when the form opens. For multi-select fields, use **Default Select Options**, with values separated by commas, such as `pcidss,hipaa`.      |

Datepicker also has:

| Option                    | What it does                                                                                                                                 |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Display Time (Yes/No)** | Adjusts the UI control to accept a date and a time from the user. It also shows the date and time every where this field is shown in the UI. |

### Suggest values with AFScript <a href="#suggest-values-with-afscript" id="suggest-values-with-afscript"></a>

A **suggested value** helps people fill in a form quickly and consistently. Instead of everyone working out the same answer by hand, a script works it out from what's already in the form, and suggests it. The user decides whether to accept it.

* **It's a script.** Suggested values are written in [AFScript](https://support.attackforge.com/app/afscript), AttackForge's scripting language.
* **It can see the whole form.** The script can use the values of every field in the form, not just its own.
* **It stays up to date.** The script runs again every time the form changes, so the suggestion always reflects the latest values.
* **The user stays in control.** The suggestion is only a suggestion. The user can accept it, or enter their own value.

For example, a suggested value could:

* suggest a target remediation date, based on the vulnerability's priority
* suggest a risk rating, from the likelihood and impact fields
* suggest a project code, from the client's organisation code and the start date
* suggest a business unit, from the affected asset

### Field types <a href="#field-types" id="field-types"></a>

| Type                   | What users see                                        | Placeholder or default | Display in Tables |
| ---------------------- | ----------------------------------------------------- | ---------------------- | ----------------- |
| **Input field**        | A single-line text box                                | Placeholder Value      | Yes               |
| **Text Area**          | A multi-line text box that users can resize           | Placeholder Value      | Yes               |
| **Select**             | A drop-down menu. Users choose one option.            | Default Select Option  | Yes               |
| **Multi-Select**       | A drop-down menu. Users choose one or more options.   | Default Select Options | Yes               |
| **List**               | A tag-style box. Each entry becomes a new row.        | —                      | Yes               |
| **Datepicker**         | A calendar for choosing a date                        | Placeholder Date       | Yes               |
| **Datetimepicker**     | A calendar for choosing a date and time               | Placeholder Date       | Yes               |
| **Table**              | A table with the columns you define. Users add rows.  | Set on each column     | —                 |
| **Rich-Text**          | A multi-line editor with formatting                   | Placeholder Value      | No                |
| **User Select**        | A drop-down menu of users. Users choose one.          | Default Select Option  | Yes               |
| **User Multi-Select**  | A drop-down menu of users. Users choose one or more.  | Default Select Options | Yes               |
| **Group Select**       | A drop-down menu of groups. Users choose one.         | Default Select Option  | Yes               |
| **Group Multi-Select** | A drop-down menu of groups. Users choose one or more. | Default Select Options | Yes               |

All types have Key, Label, Info, Required, Hide Condition and Access Controls.

### **Table columns**

Click **Add Column** to add a column to a table field. Each column has:

| Option                               | What it does                                                                |
| ------------------------------------ | --------------------------------------------------------------------------- |
| **Type**                             | Input field, Text Area, Rich-Text, Select, Multi-Select, Datepicker or List |
| **Key**                              | A unique name for the column, made of letters, numbers and underscores      |
| **Info**                             | A message shown when someone selects the column or enters data              |
| **Default Value / Selected Options** | The column's default value or options, depending on its type                |
| **Label**                            | The column's name in the form                                               |
| **Required**                         | Whether the column must be filled in                                        |

**User and group fields need access controls**

{% hint style="info" %}
**Important:** You must apply an access control to user and group fields, because they can reveal information about other users and groups.

* **User Select and User Multi-Select:** people with View access can see the profile of the user who's been chosen. People with Edit access can see the first name, last name and email address of every user, so they can choose one.
* **Group Select and Group Multi-Select:** people with View access can see the name of the group that's been chosen. People with Edit access can see every group.
  {% endhint %}

## Where custom fields appear <a href="#where-custom-fields-appear" id="where-custom-fields-appear"></a>

| Custom fields for         | Admin path                                   | Where they appear                                                                                                                                                                                       |
| ------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Project requests**      | Administration > Projects > Project Requests | Request a New Project and Edit Project Request forms; the Project Request page; the Approve Project Request with Updates form; the Pending Requests and Actioned Requests tables in the Projects module |
| **Projects**              | Administration > Projects                    | Create New Project and Edit Project forms; the Approve Project Request form; the project dashboard; the Projects and Archived Projects tables; reports                                                  |
| **Writeups**              | Administration > Writeups                    | Create and Edit Writeup forms; the writeup view in the library; the vulnerability view on a project; Writeups tables; reports                                                                           |
| **Vulnerabilities**       | Administration > Projects > Vulnerabilities  | Create and Edit Vulnerability forms; the vulnerability view on a project; Vulnerabilities tables; reports                                                                                               |
| **Assets**                | Administration > Assets                      | Create or Update Asset forms in the Assets module; the asset view; the Assets table; reports                                                                                                            |
| **Portfolios**            | Administration > Portfolios                  | Create or Update Portfolio forms; the portfolio view; the Portfolios table                                                                                                                              |
| **Test suite test cases** | Administration > Test Suites                 | Create or Update Test Case forms in the Test Suites module; test cases on a test suite; test cases on a project; reports                                                                                |
| **Project test cases**    | Administration > Projects > Test Cases       | The Update Test Case form on a project; test cases on a project; reports                                                                                                                                |
| **Reporting**             | Administration > Projects > Reporting        | The Reporting section on a project; reporting fields in reports                                                                                                                                         |
| **Summary page**          | Administration > Projects > Pages            | The summary page on a project; summary page fields in reports                                                                                                                                           |
| **Retesting**             | Administration > Projects > Retesting        | The retest round view on a project; retest round fields in reports                                                                                                                                      |
| **Groups**                | Administration > Groups                      | The group view in the Groups module                                                                                                                                                                     |
| **Users**                 | Administration > Users                       | User profile views, where the viewer has access; the user view in the Users module                                                                                                                      |

All custom fields are also available in the APIs, Flows and Events, and in the AttackForge MCP tools, so AI assistants and agents can read and update them. See [AI MCP and Skills](https://support.attackforge.com/app/modules/ai-mcp-and-skills).

## Show fields only when they're relevant <a href="#show-fields-only-when-theyre-relevant" id="show-fields-only-when-theyre-relevant"></a>

A **hide condition** hides a field or section until a condition is met. This keeps forms short, and only asks for information when it applies.

For example, a field asking for the application's URL only matters for a web application pentest. This hide condition keeps the field hidden until the project type is "web\_app\_pentest":

```
custom.project_type !== "web_app_pentest"
```

The field is hidden while the condition is **true**, and shown when it's false.

### Refer to fields <a href="#refer-to-fields" id="refer-to-fields"></a>

* `core.<key>` refers to a **system field**, which has a well-known key, such as `core.name`.
* `custom.<key>` refers to a **custom field**, using the key you gave it, such as `custom.project_type`.

Some custom fields can also refer to fields on related records:

| Custom fields on                               | Can also refer to                                                                                                                                  |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Vulnerabilities**                            | The project: `project.core.<key>` and `project.custom.<key>`                                                                                       |
| **Project test cases**                         | The project: `project.core.<key>` and `project.custom.<key>`. The test case: `test_case.core.<key>` and `test_case.custom.<key>`                   |
| **Projects, when approving a project request** | The project request: `project_request.core.<key>` and `project_request.custom.<key>`. The project: `project.core.<key>` and `project.custom.<key>` |

### Operators <a href="#operators" id="operators"></a>

| Operator       | Meaning                  |
| -------------- | ------------------------ |
| `NOT` or `!`   | Not                      |
| `AND` or `&&`  | And                      |
| `OR` or `\|\|` | Or                       |
| `==`           | Equals                   |
| `===`          | Strictly equals          |
| `!==`          | Doesn't equal            |
| `>`            | Greater than             |
| `<`            | Less than                |
| `>=`           | Greater than or equal to |
| `<=`           | Less than or equal to    |
| `( )`          | Groups conditions        |

### Examples by value type <a href="#examples-by-value-type" id="examples-by-value-type"></a>

| Type              | Hide condition                                                                 | Effect                                                                                                             |
| ----------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| **string**        | `core.name.length < 1`                                                         | Hidden until the project request name has at least one character                                                   |
| **string**        | `core.name.length > 0`                                                         | Hidden once the project request name has at least one character                                                    |
| **string**        | `core.name !== "Project Name"`                                                 | Hidden until the project request name is exactly "Project Name"                                                    |
| **string**        | `core.name == "Project Name"`                                                  | Hidden once the project request name is exactly "Project Name"                                                     |
| **string**        | `NOT (core.name =~ /Red Team/)`                                                | Hidden until the project request name matches "Red Team" anywhere within the name using a Regular Expression match |
| **string**        | `core.name =~ /Red Team/`                                                      | Hidden once the project request name matches "Red Team" anywhere within the name using a Regular Expression match  |
| **string\[]**     | `NOT ("Web App" $in custom.testing_types)`                                     | Hidden until "Web App" is selected from a multi-select list on the custom field Testing Types                      |
| **ISO date time** | `core.start_date == undefined OR core.start_date < "2023-01-01T00:00:00.000Z"` | Hidden while there's no start date, or the start date is before 1 January 2023                                     |
| **Number**        | `core.exploitability == undefined OR core.exploitability < 5`                  | Hidden until a Likelihood of Exploitation of 5 or more is chosen                                                   |
| **Boolean**       | `core.zero_day == undefined OR core.zero_day == false`                         | Hidden until "Is Zero Day?" is set to Yes                                                                          |

ISO date times use the format `YYYY-MM-DDThh:mm:ss.mmmZ`. Use `undefined` to check whether a field is empty.

### System fields you can use <a href="#system-fields-you-can-use" id="system-fields-you-can-use"></a>

A field that can be `undefined` may be empty. Check for `undefined` before comparing it, as in the examples above.

**Projects**

| Field                    | Type                                                                                                     |
| ------------------------ | -------------------------------------------------------------------------------------------------------- |
| `name`                   | string                                                                                                   |
| `code`                   | string                                                                                                   |
| `org_code`               | string                                                                                                   |
| `start_date`             | ISO date time                                                                                            |
| `end_date`               | ISO date time                                                                                            |
| `timeframe`              | Two ISO date times: start and end                                                                        |
| `linked_groups`          | string\[]                                                                                                |
| `group_ids`              | string\[]                                                                                                |
| `group_names`            | string\[]                                                                                                |
| `portfolio_ids`          | string\[]                                                                                                |
| `portfolio_names`        | string\[]                                                                                                |
| `portfolio_stream_ids`   | string\[]                                                                                                |
| `portfolio_stream_names` | string\[]                                                                                                |
| `test_suite_ids`         | string\[]                                                                                                |
| `test_suite_names`       | string\[]                                                                                                |
| `vuln_scoring_system`    | 'CVSS v3.1 Baseline', 'CVSS v3.1 Baseline + Temporal' or 'CVSS v3.1 Baseline + Temporal + Environmental' |
| `vuln_code`              | string                                                                                                   |
| `sla_apply_method`       | 'Automatic' or 'Manual'                                                                                  |

All project fields may be `undefined`.

**Project requests**

| Field                        | Type                                                                               |
| ---------------------------- | ---------------------------------------------------------------------------------- |
| `name`                       | string                                                                             |
| `code`                       | string                                                                             |
| `linked_groups`              | string\[]                                                                          |
| `onsite_testing_required`    | 'Yes' or 'No'                                                                      |
| `reason_testing_is_required` | string                                                                             |
| `desired_test_window`        | 'Mon-Fri (Business Hours)', 'Mon-Fri (Non-Business Hours)' or 'Weekends (Sat/Sun)' |
| `testing_to_be_performed`    | string\[] or string                                                                |
| `scope`                      | string\[]                                                                          |
| `desired_start_date`         | string                                                                             |
| `desired_end_date`           | string                                                                             |
| `org_code`                   | string                                                                             |

All project request fields may be `undefined`.

**Vulnerabilities**

| Field                        | Type                                                       |
| ---------------------------- | ---------------------------------------------------------- |
| `writeup_library`            | object, or `undefined`                                     |
| `writeup_library.name`       | string                                                     |
| `writeup_library.key`        | string                                                     |
| `writeup_library.type`       | 'system' or 'custom'                                       |
| `writeup`                    | object, or `undefined`                                     |
| `writeup.id`                 | string                                                     |
| `writeup.name`               | string                                                     |
| `asset_names`                | string\[]                                                  |
| `zero_day`                   | true, false or `undefined`                                 |
| `visibility_to_project_team` | true, false or `undefined`                                 |
| `priority`                   | 'Critical', 'High', 'Medium', 'Low', 'Info' or `undefined` |
| `exploitability`             | number, or `undefined`                                     |
| `steps_to_reproduce`         | string, or `undefined`                                     |
| `notes`                      | string\[], or `undefined`                                  |
| `tags`                       | string\[], or `undefined`                                  |
| `associated_test_cases`      | string\[], or `undefined`                                  |
| `project.core.<key>`         | A project system field                                     |
| `project.custom.<key>`       | A project custom field                                     |

**Writeups**

| Field                        | Type                                           |
| ---------------------------- | ---------------------------------------------- |
| `library`                    | object, or `undefined`                         |
| `library.type`               | 'system' or 'custom'                           |
| `library.key`                | string                                         |
| `import_source`              | string, or `undefined`                         |
| `import_source_id`           | string, or `undefined`                         |
| `template`                   | string, or `undefined`                         |
| `title`                      | string, or `undefined`                         |
| `description`                | string, or `undefined`                         |
| `attack_scenario`            | string, or `undefined`                         |
| `remediation_recommendation` | string, or `undefined`                         |
| `severity`                   | number, or `undefined`                         |
| `exploitability`             | number, or `undefined`                         |
| `impact_on_confidentiality`  | 'High', 'Medium', 'Low', 'None' or `undefined` |
| `impact_on_integrity`        | 'High', 'Medium', 'Low', 'None' or `undefined` |
| `impact_on_availability`     | 'High', 'Medium', 'Low', 'None' or `undefined` |
| `tags`                       | string\[], or `undefined`                      |

**Assets**

| Field           | Type                      |
| --------------- | ------------------------- |
| `name`          | string, or `undefined`    |
| `type`          | string, or `undefined`    |
| `id`            | string, or `undefined`    |
| `details`       | string, or `undefined`    |
| `linked_groups` | string\[], or `undefined` |

**Portfolios**

| Field          | Type                      |
| -------------- | ------------------------- |
| `name`         | string, or `undefined`    |
| `code`         | string, or `undefined`    |
| `description`  | string, or `undefined`    |
| `level1_owner` | string, or `undefined`    |
| `level2_owner` | string, or `undefined`    |
| `level3_owner` | string, or `undefined`    |
| `tags`         | string\[], or `undefined` |

**Test cases**

| Field            | Type                                                                 |
| ---------------- | -------------------------------------------------------------------- |
| `test_case`      | string, or `undefined`                                               |
| `details`        | string, or `undefined`                                               |
| `code`           | string, or `undefined`                                               |
| `execution_flow` | A list of steps, each with a `title` and `details`, or an empty list |
| `tags`           | string\[], or an empty list                                          |

**Project test cases**

| Field                    | Type                                                                           |
| ------------------------ | ------------------------------------------------------------------------------ |
| `status`                 | 'Tested', 'Not Tested', 'Testing In Progress', 'Not Applicable' or `undefined` |
| `assigned_to`            | string, or `undefined`                                                         |
| `project.core.<key>`     | A project system field                                                         |
| `project.custom.<key>`   | A project custom field                                                         |
| `test_case.core.<key>`   | A test case system field                                                       |
| `test_case.custom.<key>` | A test case custom field                                                       |

**Retesting**

| Field                  | Type                                       |
| ---------------------- | ------------------------------------------ |
| `window`               | Two strings: start and end, or `undefined` |
| `scope_ids`            | string\[]                                  |
| `project.custom.<key>` | A project custom field                     |

**Groups**

| Field                    | Type                   |
| ------------------------ | ---------------------- |
| `name`                   | string, or `undefined` |
| `owner`                  | string, or `undefined` |
| `primary_contact`        | object, or `undefined` |
| `primary_contact.name`   | string, or `undefined` |
| `primary_contact.number` | string, or `undefined` |
| `primary_contact.email`  | string, or `undefined` |

**Users**

| Field             | Type                                                                       |
| ----------------- | -------------------------------------------------------------------------- |
| `first_name`      | string                                                                     |
| `last_name`       | string                                                                     |
| `job_title`       | string, or `undefined`                                                     |
| `organization`    | string, or `undefined`                                                     |
| `business_group`  | string, or `undefined`                                                     |
| `office_location` | string, or `undefined`                                                     |
| `about_me`        | string, or `undefined`                                                     |
| `tags`            | string\[]                                                                  |
| `certifications`  | string\[]                                                                  |
| `education`       | A list, each with an optional `institute`, `qualification` and `completed` |
| `employment`      | A list, each with an optional `company`, `job_title` and `duration`        |

## Carry request details into the project with a linked project key <a href="#carry-request-details-into-the-project-with-a-linked-project-key" id="carry-request-details-into-the-project-with-a-linked-project-key"></a>

When a project request is approved, you may want some of its data to carry over to the new project. For example, the notes a customer adds to their request can become the project's notes, so nobody has to copy them across. Link the project request field to a project field with a **linked project key**.

1. **Create a project custom field.** For example, a field with the key `project_notes`, under **Administration > Projects**.
2. **Create a project request custom field, and link it to the project field.** For example, a field with the key `customer_notes` , under **Administration > Projects > Project Requests**, with `project_notes` as its linked project key.
3. **Create a new project request.** The new Additional Notes field appears on the request form.
4. **Approve the project request.** The project's Project Notes field now holds what the customer entered in Additional Notes.

<figure><img src="https://372186556-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M8s1QY2Q6YTHB4a6DMu%2Fuploads%2FlNV5369ISt87XrOyvrXr%2FScreenshot%202026-11-04%20at%205.28.30%E2%80%AFpm.png?alt=media&amp;token=cae771c0-40ac-40ad-bb5e-3ace6b40e899" alt=""><figcaption></figcaption></figure>

## Use custom fields with the APIs <a href="#use-custom-fields-with-the-apis" id="use-custom-fields-with-the-apis"></a>

You can create and update custom fields through the Self-Service APIs and the vulnerability import API. Fields don't need to be set up in Administration first. If a key matches a field an administrator has set up, the field takes that field's type in the UI.

{% hint style="info" %}
**Note:** Custom fields don't need to be set up by an administrator before you create them through the APIs.
{% endhint %}

Each custom field is an object with a `key` and a `value`. Keys can contain upper and lower case letters, numbers and underscores, but can't start or end with an underscore.

| Value type                    | Use it for                                                                                                            |
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| **String**                    | Input, Text Area, Datepicker, Rich-Text and Select fields. Datepicker values must be UTC strings.                     |
| **String array** (`string[]`) | Multi-Select, User Select, User Multi-Select, Group Select and Group Multi-Select fields                              |
| **Array of objects**          | Table fields. Each object is a row, and each key in it is a column. Column values must be a string or a string array. |

String:

```json
"custom_fields": [
  {
    "key": "something",
    "value": "...lorem ipsum..."
  }
]
```

String array:

```json
"custom_fields": [
  {
    "key": "something",
    "value": ["hello", "goodbye"]
  }
]
```

Array of objects, for a table:

```json
"custom_fields": [
  {
    "key": "table1",
    "value": [
      { "column1": "hello", "column2": "goodbye" },
      { "column1": "goodbye", "column2": "hello" }
    ]
  }
]
```

To **delete** a custom field, set its value to `null`:

```json
"custom_fields": [
  {
    "key": "something",
    "value": null
  }
]
```

## Add features with custom system fields <a href="#add-features-with-custom-system-fields" id="add-features-with-custom-system-fields"></a>

Custom system fields use reserved keys to turn on extra features.

### Template for steps to reproduce: `af_sys_steps_to_reproduce` <a href="#template-for-steps-to-reproduce-afsysstepstoreproduce" id="template-for-steps-to-reproduce-afsysstepstoreproduce"></a>

Give testers a consistent starting point for proof of concept, so every vulnerability records its evidence in the same structure.

1. Go to **Administration > Writeups > Custom Fields**.
2. Create a **Rich-Text** field with the key `af_sys_steps_to_reproduce`.
3. On each writeup, enter the template in this field.

When a tester adds a vulnerability to a project and chooses that writeup, the template is copied into **Steps to Reproduce** automatically.

<figure><img src="https://372186556-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M8s1QY2Q6YTHB4a6DMu%2Fuploads%2FOiHb23tHVFje2ArwSueP%2FScreenshot%202026-11-04%20at%205.32.14%E2%80%AFpm.png?alt=media&amp;token=21dc44f1-d409-44ee-a806-7109e4b1c37a" alt=""><figcaption></figcaption></figure>

## Tips <a href="#tips" id="tips"></a>

* **Plan your keys before you start.** Keys are how reports, Flows and APIs refer to fields, so choose clear, consistent names, such as `change_ticket`.
* **Use select fields instead of free text** wherever the answers are predictable. They're easier to filter and report on.
* **Group related fields into sections**, so long forms are easier to fill in.
* **Use hide conditions** to keep forms short and relevant.
* **Set access controls on sensitive fields**, and always on user and group fields.
* **Only turn on Display in Tables** for fields people need to scan or sort by, so tables stay readable.

## FAQ <a href="#faq" id="faq"></a>

**Who can create custom fields?** Only Administrators, in the Administration module.

**Can I use custom fields in reports?** Yes. Refer to them by their key in your report templates.

**Can I create custom fields through the API without setting them up first?** Yes. If the key matches a field an administrator has set up, it takes that field's type in the UI.

**How do I delete a custom field's value through the API?** Set its value to `null`.

**Can a vulnerability field depend on a project field?** Yes. Use `project.core.<key>` or `project.custom.<key>` in the hide condition.

**Why must user and group fields have an access control?** Because people who can edit them can see the names and email addresses of every user, or every group.

## Related pages <a href="#related-pages" id="related-pages"></a>

* [Creating and managing projects](https://support.attackforge.com/app/getting-started/creating-and-managing-projects)
* [Requesting a project](https://support.attackforge.com/app/getting-started/requesting-a-project)
* [Reporting](https://support.attackforge.com/app/getting-started/reporting)
* [Retesting](https://support.attackforge.com/app/getting-started/retesting)
* [Self-Service REST APIs](https://docs.attackforge.com/rest-api/pages/getting-started)
* [Flows](https://support.attackforge.com/app/modules/flows)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://support.attackforge.com/app/getting-started/custom-fields-and-forms.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
