Introduction#

The Evolu Integrators API lets third-party agencies and partners submit promotional campaign entries programmatically. Instead of routing end-users through a web form, you ingest entries directly from your own systems — CRMs, point-of-sale platforms, mobile apps, or any HTTP-capable backend.

How it works#

The integration flow follows four steps:

  1. Authenticate — Use a campaign-scoped API key issued from the Evolu dashboard.
  2. SubmitPOST an entry to the /v1/entries endpoint.
  3. Acknowledge — Receive a 202 Accepted response with the entry_id immediately, and an entry.received webhook as confirmation.
  4. Listen — Receive processing and evaluation results asynchronously via the entry.completed and entry.evaluated webhooks.

Asynchronous by design

Every entry is processed asynchronously. The API validates the payload, deduplicates it against your idempotency key, persists the entry, and queues it for processing. Lifecycle updates are delivered to your registered webhook URL.

Base URL#

All API requests are made to:

https://api.evolu.tec.br/

https://api.staging.evolu.tec.br/

The entry endpoint is therefore https://api.evolu.tec.br/v1/entries.

Core concepts#

Campaigns#

A campaign is a time-bound promotional event (e.g. "Summer Sweepstakes 2026"). Each campaign has its own rules, mechanics, and prizes. Your API key is scoped to a single campaign — you cannot submit entries across campaigns with the same key.

Entries#

An entry is a single submission on behalf of a participant. It is composed of three required objects:

enrollmentobjectrequired

Participant identity for the campaign enrollment. Only document_number (CPF or CNPJ) is always required; full_name, email, phone, birthdate, and address are optional unless the campaign marks them required.

consentobjectrequired

LGPD consent record — granted_at timestamp, ip_address, user_agent, and the accepted term_version. An optional consents array records per-category choices (marketing, data-sharing, …); see LGPD Compliance.

evidenceobjectrequired

Proof of purchase. Today only fiscal-key evidence (type: "fiscal_key") is supported.

Enrollments#

The first entry for a given document_number creates a campaign enrollment. Later entries for the same participant reuse it: any field still empty on the enrollment is filled in from the new submission, while a field that already has a value is kept — a differing value is ignored, not rejected. So you can send the full identity once and then only document_number on later entries. A campaign may require fields beyond document_number; see the Entries reference.

Idempotency#

Every request must include an Idempotency-Key header. Retrying with the same key returns the original result without creating a duplicate entry. Keys are scoped per campaign and livemode, so test and live submissions never collide. See Idempotency.

LGPD compliance#

Every entry must include a valid consent object. See LGPD Compliance.

Quick start#

curl -X POST https://api.evolu.tec.br/v1/entries \  -H "Authorization: Bearer evolu_live_your_api_key_here" \  -H "Idempotency-Key: $(uuidgen)" \  -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"    },    "evidence": {      "type": "fiscal_key",      "access_key": "35260412345678000195550010000001231123456789"    }  }'
const response = await fetch('https://api.evolu.tec.br/v1/entries', {  method: 'POST',  headers: {    Authorization: `Bearer ${process.env.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: '189.50.12.34',      user_agent: 'MyApp/1.0',      term_version: 'v2.1',    },    evidence: {      type: 'fiscal_key',      access_key: '35260412345678000195550010000001231123456789',    },  }),})const data = await response.json()console.log(data.entry_id, data.status) // UUID, "PENDING"
import os, uuid, requestsresponse = requests.post(    "https://api.evolu.tec.br/v1/entries",    headers={        "Authorization": f"Bearer {os.environ['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": "189.50.12.34",            "user_agent": "MyApp/1.0",            "term_version": "v2.1",        },        "evidence": {            "type": "fiscal_key",            "access_key": "35260412345678000195550010000001231123456789",        },    },)data = response.json()print(data["entry_id"], data["status"])  # UUID, "PENDING"

A successful submission returns 202 Accepted:

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

What happens next#

After an entry is accepted, Evolu processes it and emits webhooks at each lifecycle stage:

  1. entry.received — dispatched immediately, confirming the entry was accepted.
  2. entry.completed — dispatched once fiscal validation and fraud checks finish; the entry is now APPROVED or REJECTED.
  3. entry.evaluated — dispatched after the campaign's mechanics are evaluated, listing each mechanic and its proposed outcome.

Depending on the campaign's mechanics, you may also exchange data with Evolu:

  • Lucky numbers (automatic generation) — Evolu generates the numbers and delivers them in the entry.evaluated webhook's outcome.numbers array; just persist them.
  • Lucky numbers (manual generation) — Evolu sends the qualified quantity and series_count on entry.evaluated; you generate the numbers and submit them via the Lucky Numbers endpoint.
  • Instant prize (integrator-declared) — declare the win in the instant_win block of the entry payload; Evolu confirms it on entry.evaluated. See Instant Prize.

See Webhooks and Webhook Events.

Next steps#

GuideDescription
AuthenticationAPI key format, scoping, and rotation
IdempotencyExactly-once delivery and retry safety
LGPD ComplianceConsent requirements
Error HandlingStatus codes and error responses
WebhooksReceiving lifecycle events
Entries APIFull endpoint reference
Webhook EventsEvent envelope and payloads
Lucky NumbersSubmit externally-generated lucky numbers