> ## Documentation Index
> Fetch the complete documentation index at: https://docs.penbox.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Upsert Case Field

> Declare a field on a case, rename it, or mark a date as a deadline

Declare a field on a case, or change an existing one. [Update Case Data](https://docs.penbox.io/api-reference/cases/update-case-data.md)
writes values; a field declared here gives a value its label, its type and its flags.

* The `key` identifies the field and never changes. To rename a field, send a new `name`.
* A field that does not exist yet needs a `type`.
* The call is idempotent: replaying it lands on the same field.

## Deadlines

A deadline is a `date` field with `is_deadline: true`. Its `name` says what the deadline is
(an appeal deadline, a hearing), its value says when. Only a date field can be a deadline:
`is_deadline` on any other type is refused with a `422`.

Deadlines show in [Get Case](https://docs.penbox.io/api-reference/cases/get-case.md) under `schema.data`, with
`is_deadline: true`. To clear a deadline's date and keep the deadline, write `null` to its
value with Update Case Data. To remove the deadline itself, use
[Delete Case Field](https://docs.penbox.io/api-reference/cases/delete-case-field.md).

> [!TIP]
>
> Every change sends a `fields.updated` change in the `case.updated`
> [webhook](https://docs.penbox.io/api-reference/webhooks.md).

```bash Declare a deadline theme={null}
curl --request PUT \
  --url https://connect.penbox.io/v1/cases/{id}/fields/delai_appel \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{ "name": "Délai d'\''appel", "type": "date", "is_deadline": true }'
```

```bash Rename it theme={null}
curl --request PUT \
  --url https://connect.penbox.io/v1/cases/{id}/fields/delai_appel \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{ "name": "Délai d'\''appel (Cour)" }'
```


## OpenAPI

````yaml PUT /cases/{id}/fields/{key}
openapi: 3.0.0
info:
  title: Penbox API
  version: '1.0'
  description: >-
    The Penbox API provides programmatic access to Penbox's form management,
    case management, and document processing capabilities. Authenticate using
    Bearer tokens created at https://app.penbox.io/workspace/settings/api
servers:
  - url: https://connect.penbox.io/v1
    description: Production
security:
  - BearerAuth: []
paths:
  /cases/{id}/fields/{key}:
    parameters:
      - name: id
        in: path
        required: true
        description: Case UUID
        schema:
          type: string
          format: uuid
      - name: key
        in: path
        required: true
        description: 'Field key: letters, digits and `_`, up to 120 characters'
        schema:
          type: string
          pattern: ^[a-zA-Z0-9_]{1,120}$
    put:
      summary: Upsert Case Field
      description: >-
        Declare a field on a case, or change the label, type or deadline flag of
        an existing one. The key never changes: renaming a field is sending a
        new `name`. Replaying the same call lands on the same field.
      operationId: upsert-case-field
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              minProperties: 1
              properties:
                name:
                  type: string
                  maxLength: 255
                  description: Field label
                  example: Délai d'appel
                type:
                  type: string
                  enum:
                    - text
                    - number
                    - date
                    - file
                    - checkbox
                    - checkboxes
                    - choices
                    - signature
                  description: Field type. Required when the field does not exist yet.
                is_deadline:
                  type: boolean
                  description: >-
                    Mark a date field as a deadline. Only a `date` field can be
                    one.
      responses:
        '200':
          description: The case, as Get Case returns it
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CaseDetailed'
        '400':
          description: Empty body, a new field without `type`, or the case is a template
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Case not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            The field is invalid, e.g. `is_deadline` on a field that is not a
            date
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    CaseDetailed:
      allOf:
        - $ref: '#/components/schemas/Case'
        - type: object
          properties:
            steps:
              type: array
              description: Array of step objects representing the case workflow
              items:
                type: object
                properties:
                  id:
                    type: string
                    description: Step identifier
                  title:
                    type: string
                    description: Step title
                  status:
                    type: string
                    description: Step status
                  data:
                    type: object
                    description: Step data
            schema:
              type: object
              description: >-
                The data of the case: its declared fields with their current
                values, and the values written without a declared field.
              properties:
                data:
                  type: array
                  description: The fields declared on the case, with their values
                  items:
                    $ref: '#/components/schemas/CaseField'
                other:
                  type: array
                  description: >-
                    Values written through `/data` for a key the case does not
                    declare
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                      value: {}
            embed_links:
              type: array
              description: >-
                One embed link per contact who has the customer portal on this
                case. Empty when the case runs no portal, when the contact's
                role has no portal, or when the case requires a verification
                code.
              items:
                $ref: '#/components/schemas/CaseEmbedLink'
    Error:
      type: object
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              status:
                type: string
              title:
                type: string
              detail:
                type: string
              source:
                type: object
                properties:
                  pointer:
                    type: string
    Case:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Case UUID
        created_at:
          type: string
          format: date-time
          description: Creation timestamp
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp
        workspace:
          type: object
          description: Workspace the case belongs to
          properties:
            id:
              type: string
              format: uuid
        title:
          type: string
          description: Case title
        description:
          type: string
          nullable: true
          description: Case description
        agent:
          type: object
          description: The case agent, as far as the API exposes it.
          properties:
            instructions:
              type: string
              nullable: true
              description: The instructions the case agent follows on this case.
        locale:
          type: string
          nullable: true
          description: Language/locale code
        reference:
          type: string
          nullable: true
          description: Custom reference number
        status:
          type: string
          nullable: true
          description: Key of the current status
        status_label:
          type: string
          nullable: true
          description: >-
            Human-readable label of the current status. Custom statuses return
            the label configured on the case template, in the language it was
            written in. Built-in statuses (`draft`, `pending`, `in_progress`,
            `closed`, `cancelled`) return an English label, as the API has no
            notion of the reader's language.
          example: Waiting for documents
        parent_status:
          type: string
          enum:
            - draft
            - pending
            - in_progress
            - closed
            - cancelled
          description: Parent status
        waiting_for:
          type: string
          enum:
            - none
            - owner
            - contact
          description: Who the case is waiting for
        statuses:
          type: array
          nullable: true
          description: >-
            Statuses available on this case, inherited from its case template.
            Use it to resolve the `status` key into a readable label. Null when
            no status is configured.
          items:
            $ref: '#/components/schemas/CaseStatus'
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when archived
        silent:
          type: boolean
          description: >-
            True for a Silent case: created from a connected mailbox, not picked
            up by anyone yet, and kept out of the team's case views. It is
            picked up, for good, at the first action a person takes on it.
        contacts:
          type: array
          description: Array of contact objects
          items:
            type: object
            properties:
              id:
                type: string
                format: uuid
                description: Contact UUID
              key:
                type: string
                description: Contact identifier
              name:
                type: string
                description: Contact role/name
              email:
                type: string
                format: email
                description: Contact email
              given_name:
                type: string
                description: First name
              family_name:
                type: string
                description: Last name
              phone:
                type: string
                description: Phone number
            additionalProperties: true
        template:
          type: string
          nullable: true
          description: Template reference
        owner:
          type: object
          nullable: true
          description: Case owner information
          properties:
            id:
              type: string
              format: uuid
            email:
              type: string
              format: email
            given_name:
              type: string
            family_name:
              type: string
        actor_type:
          type: string
          nullable: true
          readOnly: true
          enum:
            - human
            - ai
            - automation
            - partner
            - system
          description: >-
            Who decided to create the case: `human` a person, `ai` a model,
            `automation` a rule configured on a case template, `partner` a
            partner integration, `system` Penbox itself or an API token.
            Read-only, and null on cases created before this was recorded.
        channel:
          type: string
          nullable: true
          readOnly: true
          enum:
            - app
            - outlook
            - mcp
            - api
            - email
            - form
            - connection
            - system
          description: >-
            The surface the case came through: the Penbox app, the Outlook
            add-in, an AI assistant, this API, an email, a completed form, a
            connection or Penbox itself. Read-only, and null on cases created
            before this was recorded.
        creator:
          type: object
          nullable: true
          readOnly: true
          description: >-
            The workspace member who created the case. Null when no person
            created it, and null on cases created before this was recorded.
            Read-only.
          properties:
            id:
              type: string
              format: uuid
            email:
              type: string
              format: email
              nullable: true
      required:
        - id
        - title
        - parent_status
    CaseField:
      type: object
      properties:
        key:
          type: string
          description: Field key, stable for the life of the field
        name:
          type: string
          description: Field label
        type:
          type: string
          description: >-
            Field type: `text`, `number`, `date`, `file`, `checkbox`,
            `checkboxes`, `choices`, `signature`…
        value:
          description: Field value
        is_reference:
          type: boolean
          description: >-
            The value is a reference of the case (searchable, shown in its
            header)
        is_deadline:
          type: boolean
          description: >-
            A date the case must meet: the field's name says what it is, its
            value when. Date fields only.
    CaseEmbedLink:
      type: object
      description: >-
        A link that opens a contact's forms inside an iframe on your own
        website. See the "Embed a case's forms" guide.
      required:
        - role
        - contact_id
        - url
      properties:
        role:
          type: string
          description: The contact role of the case (`contacts[].key`), e.g. `main`.
          example: main
        contact_id:
          type: string
          format: uuid
          description: The contact the link belongs to.
        url:
          type: string
          format: uri
          description: >-
            Opaque URL to put in an iframe: it opens the contact's next form to
            fill. Append `/<step_key>` to open that step instead. Read it from
            each response, never build it.
          example: https://form.penbox.io/embed/eyJhbGciOi...
    CaseStatus:
      type: object
      description: >-
        A status a case can take. Custom statuses are configured on the case
        template and inherited by every case created from it.
      properties:
        key:
          type: string
          description: Status key, as returned in the `status` field of a case
          example: waiting_for_documents
        label:
          type: string
          description: Human-readable label of the status
          example: Waiting for documents
        parent_status:
          type: string
          enum:
            - draft
            - pending
            - in_progress
            - closed
            - cancelled
          description: Parent status this status belongs to
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: token
      description: >-
        API token (starts with pnbx_). Create at
        https://app.penbox.io/workspace/settings/api. Include as: Authorization:
        Bearer {token}

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.