---
title: "Create a custom attribute definition"
method: POST
path: "/api/v1/ackdb/attributes"
tags: ["ackDB"]
---

# Create a custom attribute definition

`POST /api/v1/ackdb/attributes`

## Request

- Base URL: `http://localhost:3009`
- URL: `http://localhost:3009/api/v1/ackdb/attributes`
- Auth: HTTP bearer

Strict create — never an upsert; 409 if the key already exists (as an attribute OR a trait), collides with a reserved field for the scope, or starts with a registered source's `<source>_` prefix.

## Request body

- AckdbAttributeCreateRequest: Create a custom attribute definition.
  - `key` string, required: snake_case, ^[a-z][a-z0-9_]{0,63}$.
  - `label` string: Display label; defaults to a prettified key.
  - `scope` 'company' | 'contact' | 'person', required: What the fact is ABOUT. Prefer `person` for facts about a HUMAN (is_champion, do_not_contact) — they survive job changes and render on the People view. `contact` scopes the fact to ONE employment and is API-only: no console grain renders it.
  - `type` 'string' | 'number' | 'boolean' | 'date' | 'string_array', required
  - `description` string, nullable: Read by the AI agent for semantic understanding.
  - `allowedValues` string[], nullable: Enum constraint — string type only, non-empty if present.

## Response `201`

The created attribute definition.

- object
  - `data` unknown, required

## Other responses

- `400`: VALIDATION_ERROR — missing key/scope/type, bad key format (^[a-z][a-z0-9_]{0,63}$), unknown scope/type, or invalid allowedValues (non-string type, empty, or non-string items).
- `409`: ATTRIBUTE_CONFLICT — key already exists (attribute or trait, message names the owner), is a reserved field for the scope, or uses a registered source's `<source>_` prefix.

---

[API](https://skmtc.dev/floqer/apis/floqer-public-api.md) - [All operations](https://skmtc.dev/floqer/apis/floqer-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/floqer/apis/floqer-public-api/revisions/fce50dc07b20?raw)
