Entries#

The Entries endpoint is the primary interface for submitting campaign entries programmatically. Each entry is processed asynchronously — you receive 202 Accepted immediately, and lifecycle results arrive via webhooks.

Create an entry#

POST/v1/entries

Submit an entry

Accepts an entry for asynchronous processing. Requires a valid API key and an Idempotency-Key header.

Headers

Idempotency-Keystringrequired

Caller-supplied deduplication key (UUID recommended).

Request Body

Example

{  "enrollment": {    "document_number": "string",    "full_name": "string",    "email": "integrator@example.com",    "phone": "string",    "birthdate": "2026-01-15",    "address": {      "address_line_1": "string",      "address_line_2": "string",      "neighborhood": "string",      "city": "string",      "state": "string",      "zipcode": "string",      "country": "BR"    }  },  "consent": {    "granted_at": "2026-01-15T12:00:00Z",    "ip_address": "string",    "user_agent": "string",    "term_version": "string",    "consents": [      {        "consent_type": "regulation",        "granted": true      }    ]  },  "evidence": {    "type": "fiscal_key",    "access_key": "string"  },  "instant_win": {    "won": true,    "prize_definition_id": "01905a3b-7c8d-7f00-a1b2-c3d4e5f6a7b8"  }}

Schema

enrollmentobjectrequired

Enrollment identity + PII captured for the campaign enrollment. Only ``document_number`` is always required. Whether any other field is mandatory is decided per-campaign by the API channel configuration.

document_numberstringrequired

A valid CPF (11 digits) or CNPJ (14 chars). Punctuation is accepted.

full_nameunknown

Full legal name.

emailunknown

Contact email.

phoneunknown

Contact phone in E.164 format without the leading `+` (e.g. `5511999998888`). Any country is accepted.

birthdateunknown

Date of birth (YYYY-MM-DD).

addressunknown

Postal address.

consentobjectrequired

LGPD consent data — required for every API entry.

granted_atstring<date-time>required

ISO 8601 timestamp when consent was granted.

ip_addressstringrequired

IPv4 or IPv6 address of the consenting user.

user_agentstringrequired

Browser/client User-Agent string at consent time.

term_versionstringrequired

Version identifier of the accepted terms (e.g. 'v2.1').

consentsarray

Per-type consent grants (e.g. marketing, data_sharing, image_use). Optional — submitted grants are recorded as the participant's explicit choices; the implicit consents (regulation, privacy_policy, transactional) are always recorded.

consents[].consent_typeenum(regulation | privacy_policy | marketing | data_sharing | image_use | transactional | other)required

Fixed catalog of consents a participant can grant during registration. Can be one of the following: regulation, privacy_policy, marketing, data_sharing, image_use, transactional, other.

consents[].grantedbooleanrequired

Whether the participant granted this consent.

evidenceobjectrequired

Evidence submitted with the entry. Currently only FISCAL_KEY is supported.

typestring

Evidence type. Only `fiscal_key` is supported today.

access_keystringrequired

44–50 digit fiscal access key.

instant_winunknown

For campaigns running an integrator-declared instant-prize mechanic: the win outcome decided for this entry. Recorded atomically with the entry.

Responses

202Entry accepted for processing.

Example

{  "entry_id": "01905a3b-7c8d-7f00-a1b2-c3d4e5f6a7b8",  "status": "string",  "message": "Entry accepted for processing."}

Schema

entry_idstring<uuid>required
statusstringrequired

Entry status (e.g. 'PENDING').

messagestring

Human-readable result description.

401Invalid or missing API key.
403Registration window is closed.
409Idempotency conflict (entry already exists).
422Validation error in request payload.

Headers#

HeaderRequiredDescription
AuthorizationyesBearer <api_key> — see Authentication.
Idempotency-KeyyesDeduplication key, 1–128 chars — see Idempotency.
Content-Typeyesapplication/json

Request structure#

The body is composed of three required objects.

Enrollment object#

Participant identity for the campaign enrollment. document_number is the only field that is always required — it identifies the participant. Every other field is optional by default; a campaign may mark additional fields as required (see Required fields below).

The first entry for a document_number creates the enrollment. On later entries, any field left empty on the stored enrollment is filled in from the new submission — but a field that already has a value is kept as-is: a differing value is silently ignored, never overwritten and never rejected.

document_numberstringrequired

A valid CPF (11 digits) or CNPJ (14 characters). Punctuation is accepted and stripped; the checksum is verified. CNPJ participants are only accepted when the campaign permits company participants.

full_namestring

The participant's full legal name. Minimum 3 characters.

emailstring

A valid contact email address. Must be unique within the campaign — reusing an email already taken by another participant returns 422.

phonestring

A phone number in E.164 format without the leading + (e.g. 5511999998888) — the country code is required and any country is accepted. Punctuation is accepted and stripped. Must be unique within the campaign.

birthdatestring<date>

Date of birth in YYYY-MM-DD format. Must be a date in the past.

addressobject

A postal address. All sub-fields are optional: address_line_1, address_line_2, city, state (two-letter Brazilian UF), zipcode, and country (two-letter ISO-3166 code, defaults to BR).

Required fields#

A campaign can require enrollment fields beyond document_number for the API channel — any of full_name, email, phone, birthdate, city, state. A submission that leaves a required field empty and has no stored value for it is rejected with 422. Because requirements are checked against the merged enrollment, a repeat submission may omit a required field once it has already been stored. Sending an address object whose city is empty does not satisfy a city requirement.

Progressive enrollment#

Because stored fields are preserved, you can build the enrollment up over several entries. Send the full identity once — typically on the participant's first entry — then on every later entry send only document_number (plus the required consent and evidence). Evolu matches the existing enrollment and reuses the stored name, email, phone, address, and so on.

First entry — full identity:

{  "enrollment": {    "document_number": "11144477735",    "full_name": "Maria Silva",    "email": "maria@example.com",    "phone": "5511999998888"  },  "consent": { "granted_at": "...", "ip_address": "...", "user_agent": "...", "term_version": "v2.1" },  "evidence": { "type": "fiscal_key", "access_key": "..." }}

Later entries — document_number only:

{  "enrollment": { "document_number": "11144477735" },  "consent": { "granted_at": "...", "ip_address": "...", "user_agent": "...", "term_version": "v2.1" },  "evidence": { "type": "fiscal_key", "access_key": "..." }}

The second entry still resolves to Maria's enrollment with all her stored fields intact.

LGPD requirement

The consent object is mandatory for every entry. See LGPD Compliance.

granted_atstring<date-time>required

A full ISO 8601 timestamp with timezone of when consent was granted, e.g. 2026-04-30T14:30:00Z.

ip_addressstringrequired

A valid IPv4 or IPv6 address of the consenting user.

user_agentstringrequired

The client User-Agent string at consent time. Stored values over 1024 chars are truncated.

term_versionstringrequired

Identifier of the accepted terms version, e.g. v2.1.

consentsarray

Optional per-category consent choices — an array of { "consent_type": "...", "granted": bool }. consent_type is one of marketing, data_sharing, image_use, regulation, privacy_policy, transactional, or other. Submitted entries are recorded as the participant's explicit choices; regulation, privacy_policy, and transactional are recorded implicitly even when omitted. See LGPD Compliance.

Evidence object#

typestringrequired

The evidence type. Only fiscal_key is supported today.

access_keystringrequired

The 44–50 digit fiscal access key (NF-e / NFC-e / SAT).

Instant-win object#

Optional. Only for campaigns running an integrator-declared instant-prize mechanic — the win you decided for this entry, recorded atomically with it. See Instant Prize.

instant_win.wonbooleanrequired

Whether the participant won an instant prize.

instant_win.prize_definition_idstring<uuid>

The prize won — a prize id from the campaign's pool. Required when won is true, omitted when false.

Example request#

curl -X POST https://api.evolu.tec.br/v1/entries \  -H "Authorization: Bearer evolu_live_aB3dE6gH_x7K2p..." \  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \  -H "Content-Type: application/json" \  -d '{    "enrollment": {      "document_number": "11144477735",      "full_name": "Maria Silva",      "email": "maria@example.com"    },    "consent": {      "granted_at": "2026-04-30T14:30:00Z",      "ip_address": "189.50.12.34",      "user_agent": "Mozilla/5.0 (Linux; Android 14)",      "term_version": "v2.1",      "consents": [        { "consent_type": "marketing", "granted": true },        { "consent_type": "data_sharing", "granted": false }      ]    },    "evidence": {      "type": "fiscal_key",      "access_key": "35260412345678000195550010000001231123456789"    }  }'
const response = await fetch('https://api.evolu.tec.br/v1/entries', {  method: 'POST',  headers: {    Authorization: `Bearer ${EVOLU_API_KEY}`,    'Idempotency-Key': crypto.randomUUID(),    'Content-Type': 'application/json',  },  body: JSON.stringify({    enrollment: {      document_number: '11144477735',      full_name: 'Maria Silva',      email: 'maria@example.com',    },    consent: {      granted_at: new Date().toISOString(),      ip_address: clientIp,      user_agent: navigator.userAgent,      term_version: 'v2.1',      consents: [        { consent_type: 'marketing', granted: true },        { consent_type: 'data_sharing', granted: false },      ],    },    evidence: {      type: 'fiscal_key',      access_key: '35260412345678000195550010000001231123456789',    },  }),})const data = await response.json()console.log(data.entry_id)
import requests, uuidresponse = requests.post(    "https://api.evolu.tec.br/v1/entries",    headers={        "Authorization": f"Bearer {EVOLU_API_KEY}",        "Idempotency-Key": str(uuid.uuid4()),        "Content-Type": "application/json",    },    json={        "enrollment": {            "document_number": "11144477735",            "full_name": "Maria Silva",            "email": "maria@example.com",        },        "consent": {            "granted_at": "2026-04-30T14:30:00Z",            "ip_address": client_ip,            "user_agent": user_agent,            "term_version": "v2.1",            "consents": [                {"consent_type": "marketing", "granted": True},                {"consent_type": "data_sharing", "granted": False},            ],        },        "evidence": {            "type": "fiscal_key",            "access_key": "35260412345678000195550010000001231123456789",        },    },)print(response.json()["entry_id"])

Response#

A successful submission returns 202 Accepted with the entry's tracking id:

{  "entry_id": "01905a3b-7c8d-7f00-a1b2-c3d4e5f6a7b8",  "status": "PENDING",  "message": "Entry accepted for processing."}
entry_idstring<uuid>

The unique id of the created (or, on an idempotent replay, the existing) entry. Correlate it with the data.entry_id field of webhook events.

statusstring

The entry status at response time. Usually PENDING; may be REJECTED if the submission failed fast (e.g. an invalid fiscal key).

messagestring

A human-readable summary of the result.

Errors#

See Error Handling for the full list of status codes and validation rules — 401 (auth), 403 (registration closed), and 422 (payload validation, campaign configuration, a missing required enrollment field, or an email/phone already used by another participant).

Lifecycle#

After acceptance, the entry progresses through processing and evaluation, emitting entry.received, entry.completed, and entry.evaluated webhooks. See Webhook Events.