Use when creating FormEntry leads via public capture, partner app, staff POST, or CSV bulk upload, including CRM and webhook side effects; do NOT use for listing, editing, deleting, or analyzing existing leads.
التثبيت
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Use when creating FormEntry leads via public capture, partner app, staff POST, or CSV bulk upload, including CRM and webhook side effects; do NOT use for listing, editing, deleting, or analyzing existing leads.
requires
["breathecode-staff-api-index"]
Skill: Create FormEntry Leads
When to Use
Use for POST /v1/marketing/lead*, POST /v2/marketing/lead*, POST /v1/marketing/app/lead, staff POST /v1/marketing/academy/lead, or bulk PUT /v1/marketing/academy/upload.
Use when explaining what happens after a lead is submitted (CRM queue, platform webhooks, storage_status).
Permissive serializer; email is the only business-mandatory field. An empty public POST can still return 201.
CRM process
Async persist_single_lead requires location, first_name, last_name, phone, course, and (for ActiveCampaign) tags or valid automations for successful CRM sync.
A lead can exist in the database with storage_status=ERROR even when create returned 201. Diagnose with the debug skill.
location and academy resolution
Routes the lead to an academy and CRM vendor via academy alias slugs and active_campaign_slug values.
Staff POST /v1/marketing/academy/leadoverrides any client location with the session academy's active_campaign_slug.
The canonical slug sent to CRM as utm_location may differ from the raw location when aliases are configured.
tags and automations
Comma-separated slugs, scoped to the academy's CRM configuration.
ActiveCampaign: tags are required unless automations is provided. Tag types must be STRONG, SOFT, DISCOVERY, or OTHER. Tags enroll contacts and can link to automations.
Brevo: tags are not supported. Only one automation slug is allowed.
Fallback: if automations is empty, the first tag's linked automation is used (ActiveCampaign only).
app/lead merges defaults from LeadGenerationApp before applying the request body.
Discover valid slugs: GET /v1/marketing/academy/tag, GET /v1/marketing/academy/automation.
referral_key
Capture-time marker (referrer, partner, influencer code) stored on FormEntry and forwarded to CRM.
Set at create time. Filterable on staff list (manage skill).
Not the same as affiliate commission payouts (/v1/commission/... — inbound skill).
custom_fields — why it exists
custom_fields is a JSON catch-all for partner-specific, campaign, or telemetry data that does not warrant a dedicated FormEntry column.
Many values are stored and forwarded (CRM, webhooks) but are not used for platform filtering or reporting logic.
Prefer custom_fields for new partner-specific or experimental capture data instead of proposing new schema columns.
First-class fields (utm_*, email, course, referral_key, deal_status, etc.) are reserved for values the platform filters, reports, or syncs with defined semantics.
On ActiveCampaign academies, numeric keys often map to CRM custom field ids; slug-key decoding on read is documented in the inbound skill.
Pass through unknown inbound keys into custom_fields rather than dropping them.
Other sensible create fields
utm_*, gclid (v1), ppc_tracking_id (v2), lead_type, language, course, phone, current_download, client_comments. lead_generation_app is set automatically on app/lead.
Create side effects
Side effect
Public / app / bulk CSV
Staff POST /academy/lead
form_entry.added platform webhook
Yes (on save)
Yes (on save)
CRM outbound (persist_single_lead)
Auto after save
No — call PUT .../lead/process via manage skill
Geolocation enrichment
After CRM if city missing
Same if processed
Initial storage_status
PENDING → PERSISTED / ERROR / DUPLICATED
Stays PENDING until process
CRM vendor routing (ACTIVE_CAMPAIGN vs BREVO) is automatic per academy CRM config (GET /v1/marketing/crmacademy).
Outbound CRM sync: create/process pushes leads to the CRM. Reverse sync (salesperson updates deal in ActiveCampaign reflected on FormEntry) is documented in bc-marketing-debug-form-entry.
Later platform webhook events (on update or deal change): form_entry.changed, form_entry.won_or_lost, form_entry.new_deal. Subscribe via POST /v1/notify/hook/subscribe (see HOOKS_MANAGEMENT.md).
Workflow
Set context headers. Staff and bulk paths require Authorization: Token <token> and Academy: <academy_id>. Send Accept-Language (e.g. en, es) for translated errors.
Pick the create path:
Public v1:POST /v1/marketing/lead or POST /v1/marketing/lead-captcha (uses gclid).
Public v2:POST /v2/marketing/lead or POST /v2/marketing/lead-captcha (uses ppc_tracking_id, not gclid).
Partner app:POST /v1/marketing/app/lead?app_id=<slug_or_token> — defaults merged from LeadGenerationApp.
Staff manual:POST /v1/marketing/academy/lead — then PUT /v1/marketing/academy/lead/process?id=<id> if CRM sync is needed (manage skill).
Bulk CSV:PUT /v1/marketing/academy/upload with multipart file.
Build the payload. Minimum: email. For successful CRM sync also include first_name, last_name, phone, course, location (except staff POST, which overrides location), tags or automations (per vendor rules), and attribution fields (utm_*, referral_key, custom_fields).
On 201, save the returned id. For public/app/bulk paths, CRM runs asynchronously. Poll with GET /v1/marketing/academy/lead/<id> (manage skill) or load the debug skill if storage_status is ERROR or stuck PENDING.
If integrations need real-time fan-out, confirm a form_entry.added hook subscription exists (POST /v1/notify/hook/subscribe).
POST /v1/marketing/app/lead?app_id=acme-partner merges LeadGenerationApp defaults (utm_*, location, language, tags, automations, academy) then overwrites with request body fields.
Each row runs asynchronously: save → persist_single_lead (auto CRM, same as public capture).
Current behavior: the bulk task maps first_name, last_name, email, location, academy only. Extra columns (referral_key, tags, utm_*) are not applied today.