WorkBoard custom-attributes API
Read and write custom field values on Objectives, Key Results, Work Items, and Users
Read and write custom field values on Objectives, Key Results, Work Items, and Users
openapi: 3.0.1
info:
title: WorkBoard External Public Activity (Action Items) Activity (Action Items) custom-attributes API
description: <h4>This is the API documentation for WorkBoard's version 1 REST API.</h4><p>WorkBoard's API provides resources to allow developers to interact with user, goal, and metric data in WorkBoard. All resources can be accessed via REST with GET, POST, PUT, PATCH and DELETE requests. For GET requests, query parameters can be passed as part of the request URL. All GET, POST, PUT, PATCH and DELETE requests must include the Bearer Token authorization header with the provided token you generate.</p><p>Click here to view the [changelog](./changes.html).<p>Click here to view the [Open API JSON file](./openapi.json).</p><p><strong>If you are interested in working in a demo instance, please contact your WorkBoard representative.<br/>WorkBoard's production server API root is https://www.myworkboard.com/wb/apis.</strong></p>
version: 1.0.0
servers:
- url: https://demo.biz.wobo-int.com/wb/apis
description: Demo Server
tags:
- name: custom-attributes
description: Read and write custom field values on Objectives, Key Results, Work Items, and Users
paths:
/attributes/definitions:
get:
description: 'Returns every active custom field definition (id, name, fieldType, options for selects, objectType, and objectSubtype for work_item fields). Use this to discover attribute IDs and names before reading or writing values.
Omit `objectType` to receive definitions across every object type in a single response.'
operationId: CustomAttributesController_getDefinitions
parameters:
- name: objectType
required: false
in: query
description: Filter to a single object type. Omit to return definitions for every object type.
schema:
enum:
- objective
- key_result
- work_item
- user
type: string
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/OrgDefinitionsResponse'
'400':
description: Invalid objectType
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: List custom field definitions for the org
tags:
- custom-attributes
/attributes/{attributeId}/objects:
get:
description: 'Returns objects in the caller''s org that have a value set for the given custom attribute, scoped to objects the caller can view.
**Scope:**
- **Data-Admin** callers (including superusers) see every object org-wide.
- **Non-Data-Admin** callers on objective / key_result / work_item attributes see every object they can view per-row (owner, team membership, explicit grant, public-to-internal-people, etc., as enforced by wobo-okr for OKRs and by Activity::canViewActionItem for work items). This matches the per-object GET /api/custom_attribute/:id endpoint.
- **Non-Data-Admin** callers on user attributes see only their own user (at most one row). This is intentionally stricter than the per-object endpoint.
Results are ordered by object ID descending. Values for multi-select fields are returned as string arrays; all other field types return a single string or null.
**Pagination note:** for objective / key_result / work_item attributes a returned page may contain fewer than `limit` rows even when more results exist — per-row visibility filtering can exclude candidates from any given scan window. `nextOffset` reflects the underlying scan position (not the filtered row count); paginate until `nextOffset` is null.'
operationId: CustomAttributesController_getObjectsForAttribute
parameters:
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
- name: limit
required: false
in: query
description: Page size (1-100). Defaults to 50.
schema:
type: number
- name: offset
required: false
in: query
description: Number of rows to skip. Defaults to 0.
schema:
type: number
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/AttributeObjectsResponse'
'400':
description: Invalid attributeId, limit, or offset
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Custom attribute not found
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: List every object that has a value for a custom attribute
tags:
- custom-attributes
/attributes/objectives/{id}:
get:
operationId: CustomAttributesController_getObjectiveAttributes
parameters:
- name: id
required: true
in: path
description: Objective (goal) ID
schema:
type: number
- name: attributeId
required: false
in: query
description: Filter to a single attribute by ID
schema:
type: number
- name: attributeName
required: false
in: query
description: Filter to a single attribute by name (case-insensitive)
schema:
type: string
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ObjectCustomAttributesResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Objective not found, or the attributeId filter does not match a valid definition
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Get custom attribute values for an Objective
tags:
- custom-attributes
/attributes/objectives/{id}/{attributeId}:
post:
operationId: CustomAttributesController_createObjectiveAttributeValue
parameters:
- name: id
required: true
in: path
description: Objective (goal) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Objective but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Objective not found, or the attribute is not available on this Objective
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Create (set) a custom attribute value on an Objective
tags:
- custom-attributes
put:
operationId: CustomAttributesController_setObjectiveAttributeValue
parameters:
- name: id
required: true
in: path
description: Objective (goal) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Objective but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Objective not found, or the attribute is not available on this Objective
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Update a custom attribute value on an Objective
tags:
- custom-attributes
delete:
operationId: CustomAttributesController_deleteObjectiveAttributeValue
parameters:
- name: id
required: true
in: path
description: Objective (goal) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
responses:
'204':
description: Attribute value cleared successfully
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Objective but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Objective not found, or the attribute is not available on this Objective
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Clear a custom attribute value from an Objective
tags:
- custom-attributes
/attributes/key-results/{id}:
get:
operationId: CustomAttributesController_getKeyResultAttributes
parameters:
- name: id
required: true
in: path
description: Key Result (metric) ID
schema:
type: number
- name: attributeId
required: false
in: query
description: Filter to a single attribute by ID
schema:
type: number
- name: attributeName
required: false
in: query
description: Filter to a single attribute by name (case-insensitive)
schema:
type: string
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ObjectCustomAttributesResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Key Result not found, or the attributeId filter does not match a valid definition
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Get custom attribute values for a Key Result
tags:
- custom-attributes
/attributes/key-results/{id}/{attributeId}:
post:
operationId: CustomAttributesController_createKeyResultAttributeValue
parameters:
- name: id
required: true
in: path
description: Key Result (metric) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Key Result but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Key Result not found, or the attribute is not available on this Key Result
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Create (set) a custom attribute value on a Key Result
tags:
- custom-attributes
put:
operationId: CustomAttributesController_setKeyResultAttributeValue
parameters:
- name: id
required: true
in: path
description: Key Result (metric) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Key Result but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Key Result not found, or the attribute is not available on this Key Result
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Update a custom attribute value on a Key Result
tags:
- custom-attributes
delete:
operationId: CustomAttributesController_deleteKeyResultAttributeValue
parameters:
- name: id
required: true
in: path
description: Key Result (metric) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
responses:
'204':
description: Attribute value cleared successfully
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — you can view this Key Result but cannot edit it
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Key Result not found, or the attribute is not available on this Key Result
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Clear a custom attribute value from a Key Result
tags:
- custom-attributes
/attributes/work-items/{id}:
get:
operationId: CustomAttributesController_getWorkItemAttributes
parameters:
- name: id
required: true
in: path
description: Work item (workstream) ID
schema:
type: number
- name: attributeId
required: false
in: query
description: Filter to a single attribute by ID
schema:
type: number
- name: attributeName
required: false
in: query
description: Filter to a single attribute by name (case-insensitive)
schema:
type: string
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ObjectCustomAttributesResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Work item not found, or the attributeId filter does not match a valid definition
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Get custom attribute values for a Work Item
tags:
- custom-attributes
/attributes/work-items/{id}/{attributeId}:
post:
operationId: CustomAttributesController_createWorkItemAttributeValue
parameters:
- name: id
required: true
in: path
description: Work item (workstream) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Work item not found, or the attribute is not available on this Work Item
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Create (set) a custom attribute value on a Work Item
tags:
- custom-attributes
put:
operationId: CustomAttributesController_setWorkItemAttributeValue
parameters:
- name: id
required: true
in: path
description: Work item (workstream) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Work item not found, or the attribute is not available on this Work Item
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Update a custom attribute value on a Work Item
tags:
- custom-attributes
delete:
operationId: CustomAttributesController_deleteWorkItemAttributeValue
parameters:
- name: id
required: true
in: path
description: Work item (workstream) ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
responses:
'204':
description: Attribute value cleared successfully
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: Work item not found, or the attribute is not available on this Work Item
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Clear a custom attribute value from a Work Item
tags:
- custom-attributes
/attributes/users/{id}:
get:
description: Returns custom attribute values for a user. A regular token may only read its own user ID. A **Data Admin Token** (issued via WBAdmin) may read any user in the org.
operationId: CustomAttributesController_getUserAttributes
parameters:
- name: id
required: true
in: path
description: User ID
schema:
type: number
- name: attributeId
required: false
in: query
description: Filter to a single attribute by ID
schema:
type: number
- name: attributeName
required: false
in: query
description: Filter to a single attribute by name (case-insensitive)
schema:
type: string
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/ObjectCustomAttributesResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — requires a Data Admin Token to access another user
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: User not found, or the attributeId filter does not match a valid definition
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Get custom attribute values for a User
tags:
- custom-attributes
/attributes/users/{id}/{attributeId}:
post:
description: Requires a **Data Admin Token** to write attributes on behalf of another user.
operationId: CustomAttributesController_createUserAttributeValue
parameters:
- name: id
required: true
in: path
description: User ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — requires a Data Admin Token
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: User not found, or the attribute is not available on this User
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'500':
description: Internal server or upstream failure
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearer: []
summary: Create (set) a custom attribute value on a User
tags:
- custom-attributes
put:
description: Requires a **Data Admin Token** to update attributes on behalf of another user.
operationId: CustomAttributesController_setUserAttributeValue
parameters:
- name: id
required: true
in: path
description: User ID
schema:
type: number
- name: attributeId
required: true
in: path
description: Custom attribute definition ID
schema:
type: number
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeValue'
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/SetAttributeResponse'
'400':
description: Bad request, or a select value that is not registered for this custom attribute
content:
application/json:
schema:
$ref: '#/components/schemas/InvalidCustomAttributeValueErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: Forbidden — requires a Data Admin Token
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: User not found, or the attribute is not available on this User
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorRespon
# --- truncated at 32 KB (42 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/workboard/refs/heads/main/openapi/workboard-custom-attributes-api-openapi.yml