Guide

Batch runs with CSV

One row per customer, contact, respondent or panel member — the same files the EGGai app accepts, run through the SDKs.

The SDKs take rows as plain dicts/objects, so a CSV batch is: read the file, map the rows, make one call. The column names below match the app's uploaders exactly — a file that works there works here.

The schemas

ProductRequiredOptional
Offer Optimizationcustomer_id, profile offer — free text per row. Omit the column to run one campaign across the whole file.
Lead Generationcustomer_id, profile Extra columns are kept as traits. The offer is set once for the run, not per row.
Survey Responsequestion options — pipe-separated; empty for open-ended. Own respondents: customer_id, profile.
Assortment panelcustomer_id, profile audience, segment, store_type, category_spend, total_spend, current_sku — spend columns weight the answer; the rest cut the result.

Offer batch from a CSV

customer_id,profile,offer
c_8813,"fortnightly, coupon-led","15% off produce, min 500"
c_2291,"weekly family shop","15% off produce, min 500"
import csv
from eggai import EggAI

client = EggAI()
with open("offers.csv", newline="") as f:
    rows = list(csv.DictReader(f))   # customer_id is mapped for you

run = client.offers.cheapest_accepted(
    rows=rows, guidelines="discount caps at 12%",
    on_progress=lambda p: print(f"{p['pct']:.0f}%"),
)

with open("terms.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["customer_id", "accepted", "terms", "tagline"])
    for t in run:
        w.writerow([t.customer, t.accepted, t.text, t.tagline])
Column mapping is automatic. Rows may use customer_id (the CSV convention) or id (the API's) — the SDKs map one to the other. Every other column rides along untouched.

A lead list, capped to your call capacity

ranked = client.leads.rank(
    rows,                              # customer_id, profile [, traits…]
    offer     = "Fresh Picks Weekend — 15% off produce",
    max_leads = 400,                   # what six people can call in 2 days
)
for lead in ranked.qualified:
    print(lead.rank, lead.id, lead.score, lead.reason)

An assortment panel

customer_id,profile,category_spend,total_spend
c_8813,"buys the leaving line every visit",610,7900
c_2291,"weekly juice, own-label leaning",480,5400

The two spend columns matter: category_spend weights retention, total_spend sizes what walks with a store leaver. Without them every customer counts equally — directionally fine, financially wrong.

Practice first

Run the file with your practice key first. It authenticates identically but caps rows per job, so a malformed file or a wrong guideline costs you nothing. When the output reads right, switch keys and run the list.