Skip to content

Hashing, consent, and privacy

Identity normalization and hashing

Hashed fields (email_address, phone_numbers, customer_identifier, address first_name/last_name/street/postal_code, gender, uids[].id) must follow the ECAPI 1.0 normalization rules before hashing:

  • Lowercase the Roman alphabet.
  • Trim leading/trailing whitespace.
  • Remove punctuation (where applicable to the field).
  • Use UTF-8 encoding for special characters.
  • Compute the SHA256 of the normalized value and send the 64-character lowercase hex digest.

The receiver validates each hashed field as a 64-character lowercase hex string and rejects mismatches (see API reference — Error reference).

Normalization examples

Field Raw Normalized SHA256 (lowercase hex)
customer_identifier User123 user123 e606e38b0d8c19b24cf0ee3808183162ea7cd63ff7912dbb22b5e803286b4446
email_address ␣User@example.com␣ user@example.com b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514
phone_numbers +1 212-555-0000 +12125550000 7c8d08bf90ca322bcac37f99ba14e980e4b1f5ba919f7e16a030af9070ba125e
address.first_name ␣Jane␣ jane 81f8f6dde88365f3928796ec7aa53f72820b06db8664f5fe76a7eb13e24546a2
address.last_name ␣Smith␣ smith 6627835f988e2c5e50533d491163072d3f4f41f5c8b04630150debb3722ca2dd
gender ␣Female␣ female 9f165139a8c2894a47aea23b77d330eca847264224a44d5a17b19db8b9a72c08

Use these to verify your hashing implementation before sending real identifiers — a correct implementation reproduces the digests above exactly.

Where applicable, include the IAB Global Privacy Platform consent signal in user_data:

  • gpp_string — the GPP consent string.
  • gpp_sid — array of GPP section IDs.

A consent string that fails to parse does not reject the event — the event is still accepted, and the parse issue is recorded on OpenAP's side. Sending well-formed GPP is strongly recommended so your events are processed under the correct jurisdiction and consent state.

Updating and deduplicating events

Records that share the same (data_set_id, id) are merged by OpenAP, so you can correct or enrich an event by re-sending it with the same id:

  • Scalars (e.g. value, currency_code) use last-write-wins by your timestamp.
  • Arrays (e.g. uids, email_address, phone_numbers, customer_segments, address) are de-duplicated and unioned.
  • properties.items is unioned by item id, with last-write-wins for scalars inside each item.
  • ext is deep-merged with last-write-wins on conflicts.

Updates are accepted for 90 days from the first record under a given (data_set_id, id). Later updates are still received but excluded from the merged view.

To make events independently mergeable, give each logical event a stable id. Omit id only for events you never intend to update.

Merge semantics also make retries safe: re-sending the same event with the same id after a 500 or a timeout will not create duplicates in the merged view.

Data handling and privacy

  • You hash all PII. OpenAP receives only SHA256-hashed values for personal identifiers; plaintext PII never leaves your systems.
  • TLS 1.3 required. All requests use TLS 1.3; plaintext HTTP is rejected.
  • OpenAP does not log payload content. Event payloads (including hashed values) are excluded from operational logs.
  • Hashed identifiers are encrypted at rest with dedicated keys, separate from non-PII data.
  • Consent is honored. Provide GPP (gpp_string/gpp_sid) so events are processed under the correct jurisdiction and consent state.
  • Measurement-only flagging. Set user_data.mmt_only: true on events that may be used for measurement but not audience activation.