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

# Retrieve a custom field

> Returns one field definition with live usage bookkeeping (`usage_count`, `cards_using[]`). Scope: `custom_fields:read`.

Check usage before attempting structural edits: while any card references the field, `key` renames, `field_type` changes, and option-value removals return `409 custom_field_in_use` - labels, translations, position, and ADDING options stay editable at any time.



## OpenAPI

````yaml /openapi.json get /v1/custom_fields/{id}
openapi: 3.1.0
info:
  title: VEXiON cards Public API
  description: >-
    ## Rate limiting


    Two independent layers, checked in this order:


    1. **Per-IP throttle (pre-authentication).** Applied to every `/v1` request
    BEFORE the API key is checked, keyed on the caller's IP address:
       - **600 requests/minute** per IP - a flood ceiling, `429 rate_limit_error` / `rate_limited`.
       - **20 failed authentications per 15 minutes** per IP - a key-guessing ceiling. Only responses that are `401` (missing/invalid/revoked key) count against this ceiling; a `403` from a valid key that simply lacks a scope does not. `429 rate_limit_error` / `too_many_failed_attempts`.

       Both ceilings send `Retry-After` (seconds).
    2. **Per-key, per-bucket limiter (post-authentication).** Documented per
    endpoint (see each operation's `429` response and the `rate_limit` field on
    the API Key resource) - e.g. 60/min default, 120/min for transactions, plus
    the notification-broadcast and lookup-filter buckets described on their own
    endpoints.


    ### Rate-limit response headers


    Every rate-limited response carries the legacy `X-RateLimit-Limit` /
    `X-RateLimit-Remaining` / `X-RateLimit-Reset` family (the last is an **epoch
    timestamp**) AND the IETF standards-track headers, side by side:


    - `RateLimit-Policy: "<bucket>";q=<quota>;w=<window seconds>` - the static
    policy for the bucket that was hit.

    - `RateLimit: "<bucket>";r=<remaining>;t=<seconds until reset>` - live
    state. **`t` is a DURATION (seconds remaining), not the epoch timestamp
    `X-RateLimit-Reset` carries - the two are never the same value.**
  version: 1.0.0
servers:
  - url: https://api.vexioncards.one
    description: Production
  - url: https://migration.api.vexioncards.one
    description: Sandbox
security:
  - apiKey: []
tags:
  - name: Customers
  - name: Cards
  - name: Transactions
  - name: Notifications
  - name: Locations
  - name: Products
  - name: API keys
  - name: Organization
  - name: Webhook endpoints
  - name: Events
  - name: Custom fields
  - name: Team members
  - name: Icons
paths:
  /v1/custom_fields/{id}:
    get:
      tags:
        - Custom fields
      summary: Retrieve a custom field
      description: >-
        Returns one field definition with live usage bookkeeping (`usage_count`,
        `cards_using[]`). Scope: `custom_fields:read`.


        Check usage before attempting structural edits: while any card
        references the field, `key` renames, `field_type` changes, and
        option-value removals return `409 custom_field_in_use` - labels,
        translations, position, and ADDING options stay editable at any time.
      operationId: getCustomField
      parameters:
        - name: id
          in: path
          description: Custom field identifier (`cf_` prefix).
          required: true
          example: cf_jlgwnmefr6tum774axsvz677py
          schema:
            type: string
            pattern: ^cf_[A-Za-z0-9]+$
      responses:
        '200':
          description: The custom field object.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomField'
              examples:
                Field:
                  summary: In use by 3 cards
                  value:
                    id: cf_01HW9R9Z4EF7N8MTX1RVCFLD01
                    object: custom_field
                    key: department
                    description: Clinic department the patient is assigned to.
                    field_type: select
                    position: 2
                    options:
                      - value: cardio
                        label: Cardiology
                      - value: neuro
                        label: Neurology
                      - value: ortho
                        label: Orthopedics
                    date_granularity: date
                    usage_count: 3
                    cards_using:
                      - crd_l47u555jitul2m63lryijy4wya
                      - crd_eyua5rb6gzr3jtydy3fgbhcgpy
                      - crd_pkmywxjb63cng2aupvzyymxuzm
                    created_at: 1750000000
                    updated_at: 1750000000
                    label:
                      sk: Oddelenie
                      en: Department
          headers: {}
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers: {}
        '429':
          description: Rate limited - respect Retry-After.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Server error. Retry-safe on idempotent calls.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  type: api_error
                  code: internal_error
                  message: >-
                    An internal error occurred. The request may be retried with
                    the same Idempotency-Key.
                  doc_url: >-
                    https://vexioncards.mintlify.site/api-reference/errors#internal_error
                  request_id: req_5f8b2c4a9e1d3
              examples:
                Http 500 default:
                  summary: Http 500 default
                  value:
                    error:
                      type: api_error
                      code: internal_error
                      message: >-
                        An internal error occurred. The request may be retried
                        with the same Idempotency-Key.
                      doc_url: >-
                        https://vexioncards.mintlify.site/api-reference/errors#internal_error
                      request_id: req_5f8b2c4a9e1d3
          headers: {}
      deprecated: false
components:
  schemas:
    CustomField:
      type: object
      description: >-
        A reusable custom field DEFINITION - the single vocabulary used across
        the whole platform: the signup form (via each card's `form_builder`),
        the customer record (`Customer.custom.<key>`), wallet pass slots
        (`{{custom.<key>}}` in `Card.pass_fields`), and notification templates.
        Define once, reference everywhere.


        The definition owns IDENTITY (key, type, options, granularity) and
        DEFAULTS (label translations, required, position); each card's form owns
        USAGE (which fields, per-card required/order/label overrides). Limits:
        50 definitions per organization (`409 custom_field_limit_reached`), 20
        fields per card form.
      required:
        - id
        - object
        - key
        - label
        - field_type
        - created_at
      properties:
        id:
          type: string
          pattern: ^cf_[A-Za-z0-9]+$
          description: Opaque, stable, immutable. `cf_` prefix.
          example: cf_01HW9R9Z4EF7N8MTX1RVCFLD01
        object:
          type: string
          const: custom_field
          description: Always `"custom_field"`.
        key:
          type: string
          pattern: ^[a-z][a-z0-9_]{1,49}$
          description: >-
            Stable machine identifier, unique within the organization (2-50
            chars, lowercase snake). Used in `{{custom.<key>}}` templates and
            Customer `custom.<key>` payloads. **Renames are blocked while the
            field is in use** (usage_count > 0) to prevent keys diverging across
            cards.
          example: department
        label:
          anyOf:
            - type: string
              title: Single label (all languages)
              minLength: 1
              maxLength: 200
            - type: object
              title: Per-language labels
              additionalProperties:
                type: string
                minLength: 1
                maxLength: 200
              minProperties: 1
              description: >-
                Keys are language codes (`sk`, `cs`, `en`, `de`, `hu`, `hr`,
                `ro`). On write this collapses immediately to a single stored
                string - `en` if present, otherwise the first language present -
                it is not resolved per customer language at read time. Real
                per-language display lives per CARD: see
                `Card.formBuilder.fields[].translations[]`.
          description: >-
            Customer-facing label - shown on the signup form, referenced on
            wallet passes, and used in the dashboard. Plain string or
            per-language object (the platform localization pattern, same as
            `Card.name`). This is the DEFAULT - each card's `form_builder` can
            override the label per card.
        description:
          type:
            - string
            - 'null'
          maxLength: 500
          description: Internal helper text for the dashboard.
          example: Clinic department the patient is assigned to.
        field_type:
          type: string
          enum:
            - text
            - textarea
            - number
            - currency
            - date
            - boolean
            - select
            - multiselect
          description: >-
            What kind of data the field holds - drives form input, validation,
            and typed pass/notification rendering:


            | type | value shape | pass rendering |

            |---|---|---|

            | `text` | string ≤200 | as-is |

            | `textarea` | string ≤2000 | back of pass only |

            | `number` | number (`number_format` controls integer vs decimal) |
            locale-formatted number |

            | `currency` | integer, minor units, organization currency |
            locale-formatted amount (native on Apple via ISO 4217;
            server-formatted on Google) |

            | `date` | string per `date_granularity` (`YYYY` / `YYYY-MM` /
            `YYYY-MM-DD`) | locale-formatted date |

            | `boolean` | true / false | localized Yes/No |

            | `select` | one option `value` | the option's label, customer
            language |

            | `multiselect` | array of option `value`s | comma-joined labels |


            Immutable while the field is used by any card (`409
            custom_field_in_use`).
          example: select
        position:
          type: integer
          description: >-
            DEFAULT form position when added to a card; each card's
            `form_builder` ordering overrides.
          example: 2
        options:
          type: array
          items:
            type: object
            properties:
              value:
                type: string
                description: >-
                  Stored machine value - immutable once any customer has stored
                  it.
              label:
                anyOf:
                  - type: string
                    title: Single label (all languages)
                    minLength: 1
                    maxLength: 100
                  - type: object
                    title: Per-language labels
                    additionalProperties:
                      type: string
                      minLength: 1
                      maxLength: 100
                    minProperties: 1
                    description: >-
                      Keys are language codes (`sk`, `cs`, `en`, `de`, `hu`,
                      `hr`, `ro`). On write this collapses immediately to a
                      single stored string - `en` if present, otherwise the
                      first language present - it is not resolved per customer
                      language at read time. Real per-language display lives per
                      CARD: see `Card.formBuilder.fields[].translations[]`.
                description: >-
                  Display label for the option - localizable; shown on the form
                  and rendered on passes/notifications in the customer's
                  language. Always editable.
          description: >-
            Choices for `select` / `multiselect` (required for those types).
            Each option is `{value, label}` - **labels are always editable**
            (display only); **values are immutable once any customer has stored
            them** and removing a used value is blocked (`409
            custom_field_in_use`). Adding options is always allowed.
          example:
            - value: cardio
              label: Cardiology
            - value: neuro
              label: Neurology
        date_granularity:
          type: string
          enum:
            - year
            - monthYear
            - date
          description: >-
            DATE type only - controls the stored format: `date` → YYYY-MM-DD,
            `monthYear` → YYYY-MM, `year` → YYYY. Forced to `date` for non-date
            types.
          example: date
        usage_count:
          type: integer
          description: >-
            Read-only. Number of cards referencing this field. Renames + type
            changes + deletes are blocked while > 0.
          example: 3
        cards_using:
          type: array
          items:
            type: string
          description: Read-only. The referencing card ids.
          example:
            - crd_sophcrprtvpmmnwxah2lomnkee
        created_at:
          type: integer
          description: Unix seconds.
          example: 1750000000
        updated_at:
          type: integer
          description: Unix seconds.
          example: 1750000000
        number_format:
          type:
            - string
            - 'null'
          enum:
            - integer
            - decimal
            - null
          description: >-
            `number` fields only: `integer` rejects fractional input; `decimal`
            (default) allows it. Null on other types.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - code
            - message
          properties:
            type:
              type: string
              enum:
                - invalid_request_error
                - authentication_error
                - permission_error
                - not_found_error
                - rate_limit_error
                - idempotency_error
                - api_error
            code:
              type: string
            message:
              type: string
            retry_after:
              type: integer
              description: >-
                Seconds to wait before retrying. Present on rate-limit (429) and
                idempotency-key-in-use (409) errors; mirrors the `Retry-After`
                HTTP header. Absent on error types that carry no retry guidance.
              example: 5
            param:
              type:
                - string
                - 'null'
            request_id:
              type: string
            doc_url:
              type: string
              format: uri
            field_errors:
              type: array
              description: >-
                Per-field errors on a 422. At most 100 entries: a request with
                more errors gets the first 100.
              items:
                type: object
                properties:
                  param:
                    type: string
                  code:
                    type: string
                  message:
                    type: string
                  expected_currency:
                    type: string
                    description: >-
                      On `currency_mismatch`: the business currency the request
                      must use. Absent on every other field error.
          description: >-
            The error payload: type (category), code (machine-readable), message
            (human-readable), retry_after (seconds, on
            rate-limit/idempotency-in-use errors only), param (offending field),
            request_id, doc_url, field_errors[].
      description: >-
        Standard error envelope. Branch on `error.code`; include
        `error.request_id` in support requests. See the Errors guide.
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        Your secret API key as a Bearer token: `Authorization: Bearer
        vxn_sk_...`. Keys are created and scoped in the dashboard - see
        [Authentication](/api-reference/introduction#authentication).

````

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