Skip to content

Profile attributes

Profiles carry structured attributes beyond name and phone number: loyalty tier, favorite store, preferred category, and anything else your CRM holds. You use them to build segments, target journeys and personalize messages.

You do not declare attributes before sending them. Push any key you like: unknown keys are auto-registered as custom attributes on first use. Send values as a flat map of strings:

{
"external_id": "crm-customer-4815",
"attributes": {
"tier": "gold",
"favorite_store": "lyon-part-dieu"
}
}

Keep keys stable once you start using them: segments and journeys reference them by name.

  • Inline on the profile upsert (POST /v1/profiles): send attributes alongside the profile. The profile is created or updated and the attributes are applied in the same call.
  • On their own (POST /v1/profiles/{profile_id}/attributes): set attributes on an existing profile. Unlike the upsert, this does not lazy-create the profile: it returns 404 if the reference resolves to no profile.

Read them back with GET /v1/profiles/{profile_id}/attributes.

Over the API, attribute values are always sent as strings: represent a number or a boolean as its string form ("1450", "true"). Do not nest objects or arrays in a value.

The type lives on the attribute, not on each value. Every attribute has a declared type: text, number, boolean, date, currency or enum (a closed list of allowed values). The declared type drives the comparisons offered in segments: a number range, a boolean toggle, a date window, a value picker, rather than plain string matching.

When an unknown key is auto-registered, its type is inferred from the first value received: "true" or "false" registers as boolean, a numeric string as number, an ISO 8601 date ("2026-06-10") as date, anything else as text. Currency and enum are never inferred: assign them from the app.

The inferred type is only a starting point. You can change an attribute’s type at any time in the Noticia app, under Integrations -> Attribute catalog. Changing the type is non-destructive: stored values are kept as-is, nothing is migrated or rejected. A value the new type cannot interpret (for example "n/a" under the number type) simply stops matching segment filters on that attribute; it never causes an error. Before you confirm a type change, the app shows how many stored values would stop matching.