Skip to main content

End-user identifier (end_user)

Every question sent to /v1/ask must carry end_user: an opaque identifier of the person who asked in your system. Datafala uses this value only to count active users per month, which is the basis of the band-based monthly fee.

What to send​

A value derived from the person's internal ID, never the personal data itself. Do not send a name, email, CPF or the ID in plain text.

  • Format: 16 to 128 characters made of letters, numbers, _ and -. SHA-256/HMAC hexadecimal (64 characters), base64url and UUID are accepted. Emails, names, spaces and short IDs (such as 42) are rejected with 422 invalid_end_user.
  • Stable: the same person always generates the same value, in every question and in every month.
  • Individual: never use the same value for two people (a service account or a generic admin user). A shared value counts as one person only and shows up in audit signals.
  • Fixed secret: generate the value with a secret that stays only on your server (DATAFALA_END_USER_SECRET).
Do not change the secret

After a change, each person starts generating another value and is counted again in the month of the change, which changes the band on the invoice.

Examples​

Python:

import hashlib
import hmac
import os

SECRET = os.environ["DATAFALA_END_USER_SECRET"].encode()


def datafala_end_user(user_id: int | str) -> str:
return hmac.new(SECRET, str(user_id).encode(), hashlib.sha256).hexdigest()

Node.js:

import { createHmac } from "node:crypto";

export function datafalaEndUser(userId) {
return createHmac("sha256", process.env.DATAFALA_END_USER_SECRET)
.update(String(userId))
.digest("hex");
}

PHP:

function datafala_end_user(string|int $userId): string {
return hash_hmac('sha256', (string) $userId, getenv('DATAFALA_END_USER_SECRET'));
}

A public, stable UUID of the user also works, as long as it does not change over time.

To generate the secret once:

python3 -c "import secrets; print(secrets.token_hex(32))"

Requirement and limit​

  • If your tenant requires the field and the question comes without it, the response is 400 end_user_required. New customers already start requiring it.
  • Each end_user can make 10 questions per minute. Above that, 429 rate_limited with details.scope = "end_user".
  • Requests refused with 429 do not count as an active user. Questions that fail during generation (sql_rejected, no_answer, llm_error) do count, because the person used the system.

Privacy​

The value received does not go into logs, responses, history or metrics. It is stored only as HMAC-SHA256 with a salt specific to your tenant, never linked to a question, and the counting records are deleted after 13 months.