Skip to main content
This walks through the hero curl from the marketing site — create a person, declare a new schema attribute, then write the attribute on that person, and watch enum validation reject a bad value.

1. Get an API key

Sign up at $SALTY_WEB/signup — see Introduction → Hosts at a glance for the env vars. After email verification you land on /api with your first sk_live_… key shown ONCE — store it as $SALTY_API_KEY:
export SALTY_API_KEY=sk_live_...
(For purely scripted setups, hit POST $SALTY_API/workspaces/bootstrap with a Supabase JWT to provision a workspace + first key idempotently.)
Only the first 16 characters (sk_live_xxxxxxxx) are stored on the server, hashed with argon2. If you lose the full key, revoke it and create a new one.

2. Create a person

curl $SALTY_API/people \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@acme.com",
    "first_name": "Jane",
    "last_name": "Doe"
  }'
Response:
{
  "id": "f30057e8-8f1e-49c3-a06f-481d6f03256a",
  "email": "jane@acme.com",
  "first_name": "Jane",
  "last_name": "Doe",
  "primary_company_id": null,
  "custom_attributes": {},
  "created_at": "2026-05-24T02:45:46.417Z",
  "updated_at": "2026-05-24T02:45:46.417Z"
}

3. Add a custom attribute to the People schema

Define a lifecycle_stage enum on the person object. Now every person write that includes custom_attributes.lifecycle_stage is validated against this enum.
curl $SALTY_API/schema/person/attributes \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attribute_key": "lifecycle_stage",
    "display_name": "Lifecycle Stage",
    "data_type": "enum",
    "enum_values": ["lead", "customer", "churned"]
  }'

4. Use the new attribute

curl -X PATCH $SALTY_API/people/<id> \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"custom_attributes":{"lifecycle_stage":"customer"}}'
Returns 200 with the updated person.

5. Watch validation reject a bad value

curl -X PATCH $SALTY_API/people/<id> \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"custom_attributes":{"lifecycle_stage":"vip"}}'
Returns 400 with the precise error envelope:
{
  "error": {
    "type": "invalid_request",
    "code": "attribute_enum_invalid",
    "message": "\"vip\" is not a valid value for \"lifecycle_stage\"; expected one of: lead, customer, churned",
    "param": "lifecycle_stage"
  }
}

Where to go next