> ## Documentation Index
> Fetch the complete documentation index at: https://lifters.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Guia de Exportação S3 por Domínio

> Schema Parquet e exemplos de exportação por domínio de evento (user, casino, transaction, sportsbook).

# Guia de Exportação S3 por Domínio

## Estrutura de particionamento (todos os domínios)

```
s3://seu-bucket/{domain}_events/
    organization_id={org_id}/
        brand_id={brand_id}/
            year={YYYY}/
                month={MM}/
                    day={DD}/
                        events_part_0001.parquet
                        events_part_0002.parquet
```

<Tip>
  Cada arquivo Parquet deve ter no máximo **500 MB**. Um arquivo por dia é aceitável; vários arquivos por dia também funcionam.
</Tip>

***

## Domínio: User (register / update) \[#user]

### Schema obrigatório

| Coluna                  | Tipo Parquet     | Obrigatório | Descrição                                                                             |
| ----------------------- | ---------------- | :---------: | ------------------------------------------------------------------------------------- |
| `eid`                   | STRING           |      ✓      | ID único do evento (UUID v4 ou v7)                                                    |
| `organization_id`       | STRING           |      ✓      | ID da organização                                                                     |
| `brand_id`              | STRING           |      ✓      | ID da brand                                                                           |
| `user_ext_id`           | STRING           |      ✓      | ID do usuário no seu sistema                                                          |
| `event`                 | STRING           |      ✓      | `register` ou `update`                                                                |
| `timestamp`             | TIMESTAMP (UTC)  |      ✓      | Momento do evento                                                                     |
| `status`                | STRING           |             | `ACTIVE`, `BLOCKED`, `SUSPENDED`, `BANNED`, `SELF_EXCLUDED`, `DEACTIVATED`, `PENDING` |
| `full_name`             | STRING           |             |                                                                                       |
| `first_name`            | STRING           |             |                                                                                       |
| `last_name`             | STRING           |             |                                                                                       |
| `email`                 | STRING           |             |                                                                                       |
| `phone`                 | STRING           |             |                                                                                       |
| `document`              | STRING           |             | CPF/documento                                                                         |
| `birthdate`             | TIMESTAMP (UTC)  |             |                                                                                       |
| `gender`                | INT32            |             | 1=M, 2=F, 9=outro (ISO/IEC 5218)                                                      |
| `country`               | STRING (2 chars) |             | ISO 3166 Alpha-2, ex: `BR`                                                            |
| `state`                 | STRING (2 chars) |             | Sigla do estado                                                                       |
| `city`                  | STRING           |             |                                                                                       |
| `post_code`             | STRING           |             |                                                                                       |
| `registered_at`         | TIMESTAMP (UTC)  |             | Data de cadastro original                                                             |
| `updated_at`            | TIMESTAMP (UTC)  |             |                                                                                       |
| `registration_platform` | STRING           |             | `DESKTOP`, `MOBILE`, `APP`                                                            |
| `kyc_status`            | STRING           |             | `VERIFIED`, `PENDING`, `REJECTED`                                                     |
| `is_test_account`       | BOOL             |             |                                                                                       |
| `ip`                    | STRING           |             |                                                                                       |
| `geolocation_lat`       | FLOAT64          |             |                                                                                       |
| `geolocation_long`      | FLOAT64          |             |                                                                                       |

<Warning>
  Não inclua `ingestion_source` ou `ingested_at` — são preenchidos automaticamente pela plataforma.
</Warning>

### Exemplo Python (pandas + pyarrow)

```python theme={null}
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
import s3fs
from datetime import datetime, timezone

df = pd.DataFrame([{
    "eid":                  "b7c3e8a0-1234-7bcd-8901-abcdef012345",
    "organization_id":      "org_123",
    "brand_id":             "brand_456",
    "user_ext_id":          "user_789",
    "event":                "register",
    "timestamp":            datetime(2025, 10, 15, 14, 30, 0, tzinfo=timezone.utc),
    "status":               "ACTIVE",
    "full_name":            "João Silva",
    "email":                "joao@exemplo.com",
    "document":             "12345678900",
    "country":              "BR",
    "state":                "SP",
    "city":                 "São Paulo",
    "registered_at":        datetime(2025, 10, 15, 14, 30, 0, tzinfo=timezone.utc),
    "registration_platform": "MOBILE",
    "kyc_status":           "VERIFIED",
    "is_test_account":      False,
}])

schema = pa.schema([
    pa.field("eid", pa.string()),
    pa.field("organization_id", pa.string()),
    pa.field("brand_id", pa.string()),
    pa.field("user_ext_id", pa.string()),
    pa.field("event", pa.string()),
    pa.field("timestamp", pa.timestamp("ms", tz="UTC")),
    pa.field("status", pa.string(), nullable=True),
    pa.field("full_name", pa.string(), nullable=True),
    pa.field("email", pa.string(), nullable=True),
    pa.field("document", pa.string(), nullable=True),
    pa.field("country", pa.string(), nullable=True),
    pa.field("state", pa.string(), nullable=True),
    pa.field("city", pa.string(), nullable=True),
    pa.field("registered_at", pa.timestamp("ms", tz="UTC"), nullable=True),
    pa.field("registration_platform", pa.string(), nullable=True),
    pa.field("kyc_status", pa.string(), nullable=True),
    pa.field("is_test_account", pa.bool_(), nullable=True),
])

table = pa.Table.from_pandas(df, schema=schema, preserve_index=False)
pq.write_table(
    table,
    "s3://seu-bucket/user_events/organization_id=org_123/brand_id=brand_456/year=2025/month=10/day=15/events_part_0001.parquet",
    filesystem=s3fs.S3FileSystem(),
)
```

***

## Domínio: Casino (open / win / lose) \[#casino]

### Schema obrigatório

| Coluna                 | Tipo Parquet    | Obrigatório | Descrição                                                               |
| ---------------------- | --------------- | :---------: | ----------------------------------------------------------------------- |
| `eid`                  | STRING          |      ✓      |                                                                         |
| `organization_id`      | STRING          |      ✓      |                                                                         |
| `brand_id`             | STRING          |      ✓      |                                                                         |
| `user_ext_id`          | STRING          |      ✓      |                                                                         |
| `event`                | STRING          |      ✓      | `open`, `win`, `lose`                                                   |
| `timestamp`            | TIMESTAMP (UTC) |      ✓      |                                                                         |
| `currency`             | STRING          |      ✓      | `BRL`, `USD`, etc.                                                      |
| `bet_id`               | STRING          |             |                                                                         |
| `casino_session_id`    | STRING          |             |                                                                         |
| `bet_dt`               | TIMESTAMP (UTC) |             |                                                                         |
| `bet_status`           | STRING          |             | `open`/`win`/`lose` (normalizado para `OPEN`/`WIN`/`LOSS` internamente) |
| `bet_amount`           | DECIMAL(18,2)   |             |                                                                         |
| `bet_amount_bonus`     | DECIMAL(18,2)   |             |                                                                         |
| `win_amount`           | DECIMAL(18,2)   |             |                                                                         |
| `win_amount_bonus`     | DECIMAL(18,2)   |             |                                                                         |
| `after_balance`        | DECIMAL(18,2)   |             |                                                                         |
| `before_balance`       | DECIMAL(18,2)   |             |                                                                         |
| `game_ext_id`          | STRING          |             |                                                                         |
| `game_name`            | STRING          |             |                                                                         |
| `game_provider`        | STRING          |             |                                                                         |
| `game_provider_ext_id` | STRING          |             |                                                                         |
| `game_type`            | STRING          |             | `SLOT`, `TABLE`, `LIVE`                                                 |
| `is_free_bet`          | BOOL            |             |                                                                         |
| `platform`             | STRING          |             | `WEB`, `MOBILE`, `APP`                                                  |

<Warning>
  `bet_amount` e `win_amount` **devem ser Decimal** (não Float) para evitar erros de arredondamento.
</Warning>

***

## Domínio: Transaction (deposit / withdraw) \[#transaction]

### Schema obrigatório

| Coluna                 | Tipo Parquet    | Obrigatório | Descrição                                   |
| ---------------------- | --------------- | :---------: | ------------------------------------------- |
| `eid`                  | STRING          |      ✓      |                                             |
| `organization_id`      | STRING          |      ✓      |                                             |
| `brand_id`             | STRING          |      ✓      |                                             |
| `user_ext_id`          | STRING          |      ✓      |                                             |
| `event`                | STRING          |      ✓      | `deposit`, `withdraw`                       |
| `timestamp`            | TIMESTAMP (UTC) |      ✓      |                                             |
| `transaction_id`       | STRING          |             |                                             |
| `transaction_dt`       | TIMESTAMP (UTC) |             |                                             |
| `amount`               | DECIMAL(18,2)   |             |                                             |
| `status`               | STRING          |             | `RECEIVED`, `APPROVED`, `PENDING`, `DENIED` |
| `currency`             | STRING          |             |                                             |
| `payment_method`       | STRING          |             | `PIX`, `TED`, `CREDIT_CARD`                 |
| `payment_provider`     | STRING          |             |                                             |
| `bonus_credited`       | BOOL            |             |                                             |
| `bonus_code`           | STRING          |             |                                             |
| `kyc_verified`         | BOOL            |             |                                             |
| `is_first_transaction` | BOOL            |             |                                             |
| `after_balance`        | DECIMAL(18,2)   |             |                                             |
| `before_balance`       | DECIMAL(18,2)   |             |                                             |

***

## Domínio: Sportsbook (open / win / lose / cashout / refund / cancel / pending) \[#sportsbook]

### Campos principais

| Coluna             | Tipo Parquet    | Obrigatório | Descrição                                                       |
| ------------------ | --------------- | :---------: | --------------------------------------------------------------- |
| `eid`              | STRING          |      ✓      |                                                                 |
| `organization_id`  | STRING          |      ✓      |                                                                 |
| `brand_id`         | STRING          |      ✓      |                                                                 |
| `user_ext_id`      | STRING          |      ✓      |                                                                 |
| `event`            | STRING          |      ✓      | `open`, `win`, `lose`, `cashout`, `refund`, `cancel`, `pending` |
| `timestamp`        | TIMESTAMP (UTC) |      ✓      |                                                                 |
| `currency`         | STRING          |      ✓      |                                                                 |
| `bet_id`           | STRING          |             |                                                                 |
| `bet_dt`           | TIMESTAMP (UTC) |             |                                                                 |
| `ticket_status`    | STRING          |             | `open`, `win`, `lose`, `cancel`, `cashout`, `refund`, `reject`  |
| `bet_type`         | STRING          |             | `SINGLE`, `MULTIPLE`, `SYSTEM`                                  |
| `bet_amount`       | DECIMAL(18,2)   |             |                                                                 |
| `bet_amount_bonus` | DECIMAL(18,2)   |             |                                                                 |
| `bet_odds`         | FLOAT64         |             |                                                                 |
| `bet_platform`     | STRING          |             | `WEB`, `MOBILE`, `APP`                                          |
| `bet_timing`       | STRING          |             | `LIVE`, `PREMATCH`                                              |
| `bet_virtual`      | BOOL            |             |                                                                 |
| `win_amount`       | DECIMAL(18,2)   |             |                                                                 |
| `after_balance`    | DECIMAL(18,2)   |             |                                                                 |
| `before_balance`   | DECIMAL(18,2)   |             |                                                                 |

### Campos de selections (formato COLUMNAR — obrigatório)

<Warning>
  As selections devem ser exportadas em **formato columnar** (uma coluna por atributo, cada coluna é um array). **NÃO** use array de objetos JSON. Prefixo das colunas: `selection_*` (singular).
</Warning>

| Coluna                  | Tipo Parquet  | Descrição                                 |
| ----------------------- | ------------- | ----------------------------------------- |
| `selection_id`          | LIST(STRING)  |                                           |
| `selection_status`      | LIST(STRING)  |                                           |
| `selection_choice`      | LIST(STRING)  | Ex: `OVER_2.5`                            |
| `selection_sport_type`  | LIST(STRING)  | Ex: `SOCCER`                              |
| `selection_league`      | LIST(STRING)  |                                           |
| `selection_market`      | LIST(STRING)  |                                           |
| `selection_odds`        | LIST(FLOAT64) |                                           |
| `selection_is_live`     | LIST(BOOL)    |                                           |
| `selection_virtual`     | LIST(BOOL)    |                                           |
| `selection_home_team`   | LIST(STRING)  |                                           |
| `selection_away_team`   | LIST(STRING)  |                                           |
| `selection_competitors` | LIST(STRING)  | Concatenação (ex: `"Flamengo,Palmeiras"`) |
| `selection_event_name`  | LIST(STRING)  |                                           |
| `sport_match_id`        | LIST(STRING)  |                                           |

### Exemplo Python — converter array de objetos → columnar

```python theme={null}
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
from datetime import datetime, timezone

raw_bets = [{
    "eid": "sport-eid-001",
    "organization_id": "org_123",
    "brand_id": "brand_456",
    "user_ext_id": "user_789",
    "event": "open",
    "timestamp": datetime(2025, 10, 15, 20, 0, 0, tzinfo=timezone.utc),
    "bet_id": "bilhete_001",
    "ticket_status": "open",
    "bet_amount": 50.00,
    "bet_odds": 2.75,
    "currency": "BRL",
    "bet_timing": "LIVE",
    "bet_platform": "MOBILE",
    "selections": [
        {
            "selection_id": "sel-001",
            "selection_status": "open",
            "selection_sport_type": "SOCCER",
            "selection_league": "Campeonato Brasileiro",
            "selection_market": "1X2",
            "selection_choice": "1",
            "selection_odds": 1.80,
            "selection_is_live": True,
            "selection_virtual": False,
            "selection_home_team": "Flamengo",
            "selection_away_team": "Palmeiras",
            "selection_competitors": "Flamengo,Palmeiras",
            "selection_event_name": "FLA x PAL",
            "sport_match_id": "match-001",
        },
    ],
}]


def to_columnar(bets):
    """Converte selections de array-de-objetos para colunar."""
    result = []
    for bet in bets:
        sels = bet.pop("selections", [])
        flat = {
            "selection_id":          [s.get("selection_id", "")          for s in sels],
            "selection_status":      [s.get("selection_status", "")      for s in sels],
            "selection_choice":      [s.get("selection_choice", "")      for s in sels],
            "selection_sport_type":  [s.get("selection_sport_type", "")  for s in sels],
            "selection_league":      [s.get("selection_league", "")      for s in sels],
            "selection_market":      [s.get("selection_market", "")      for s in sels],
            "selection_odds":        [float(s.get("selection_odds", 0))  for s in sels],
            "selection_is_live":     [bool(s.get("selection_is_live", False)) for s in sels],
            "selection_virtual":     [bool(s.get("selection_virtual", False)) for s in sels],
            "selection_home_team":   [s.get("selection_home_team", "")   for s in sels],
            "selection_away_team":   [s.get("selection_away_team", "")   for s in sels],
            "selection_competitors": [s.get("selection_competitors", "") for s in sels],
            "selection_event_name":  [s.get("selection_event_name", "")  for s in sels],
            "sport_match_id":        [s.get("sport_match_id", "")        for s in sels],
        }
        result.append({**bet, **flat})
    return result


rows = to_columnar(raw_bets)

schema = pa.schema([
    pa.field("eid", pa.string()),
    pa.field("organization_id", pa.string()),
    pa.field("brand_id", pa.string()),
    pa.field("user_ext_id", pa.string()),
    pa.field("event", pa.string()),
    pa.field("timestamp", pa.timestamp("ms", tz="UTC")),
    pa.field("bet_id", pa.string(), nullable=True),
    pa.field("ticket_status", pa.string(), nullable=True),
    pa.field("bet_amount", pa.decimal128(18, 2), nullable=True),
    pa.field("bet_odds", pa.float64(), nullable=True),
    pa.field("currency", pa.string()),
    pa.field("bet_timing", pa.string(), nullable=True),
    pa.field("bet_platform", pa.string(), nullable=True),
    pa.field("selection_id", pa.list_(pa.string())),
    pa.field("selection_status", pa.list_(pa.string())),
    pa.field("selection_choice", pa.list_(pa.string())),
    pa.field("selection_sport_type", pa.list_(pa.string())),
    pa.field("selection_league", pa.list_(pa.string())),
    pa.field("selection_market", pa.list_(pa.string())),
    pa.field("selection_odds", pa.list_(pa.float64())),
    pa.field("selection_is_live", pa.list_(pa.bool_())),
    pa.field("selection_virtual", pa.list_(pa.bool_())),
    pa.field("selection_home_team", pa.list_(pa.string())),
    pa.field("selection_away_team", pa.list_(pa.string())),
    pa.field("selection_competitors", pa.list_(pa.string())),
    pa.field("selection_event_name", pa.list_(pa.string())),
    pa.field("sport_match_id", pa.list_(pa.string())),
])

df = pd.DataFrame(rows)
table = pa.Table.from_pandas(df, schema=schema, preserve_index=False)
pq.write_table(
    table,
    "s3://seu-bucket/sportsbook_events/organization_id=org_123/brand_id=brand_456/year=2025/month=10/day=15/events_part_0001.parquet",
)
```
