Odoo CRM guide

Connect an Odoo CRM to your Offertown program: referral leads flow into Odoo as CRM leads, and conversions flow back the moment a referred lead becomes a paying customer. Built entirely on the REST API — a small connector you control, no Offertown code inside your Odoo database.

Requirements

  • An approved Offertown partner account with an API key (oft_…) from the partner dashboard — keep it server-side, e.g. in ir.config_parameteror your connector’s settings.
  • Odoo 16 or newer. On odoo.sh or on-premise the connector is a small custom module; on Odoo Online (SaaS), where custom Python isn’t available, run the same logic as an external service talking to Odoo over its external API — note Odoo Online only exposes the external API on Custom plans.

How the integration fits together

FlowDirectionMechanism
Leads into OdooOffertown → OdooA scheduled action (ir.cron) polls the referral list endpoint and creates crm.lead records.
Conversions backOdoo → OffertownAn automated action fires on your conversion event and calls the convert endpoint.

The join key is the Offertown referralId, stored in a custom field on the lead at import time. It travels with the record through your pipeline, so reporting the conversion later needs no fuzzy matching on emails or names.

Flow 1 — sync referrals into Odoo

GET/api/v1/partners/referrals

Run a scheduled action every 5–15 minutes that keeps a watermark of the last successful sync:

  1. Call the list endpoint with status=pending, dateFrom set to the watermark, dateTo set to the sync start time, and sortBy=createdAt&sortOrder=asc, paginating with page/pageSize. If the response reports pagination.truncated: true, split the window and repeat.
  2. For each referral whose referralIdisn’t in Odoo yet, create a crm.lead using the mapping below. Put a unique constraint on x_offertown_referral_id so replays are harmless no-ops.
  3. Advance the watermark to the run’s dateTo only after the run completes successfully.

One subtlety: a referral can start as clicked and become pending later without its createdAt changing, so a creation-time watermark alone can miss late-identified leads. Add a periodic reconciliation pass (daily is fine) that re-queries status=pending over the full 90-day attribution window — the referralId dedupe makes it idempotent.

Offertown fieldOdoo crm.lead field
referralIdx_offertown_referral_id (custom, indexed) — the join key
referralCodex_offertown_referral_code (custom) — handy for support
name (required by crm.lead) — e.g. “Offertown referral — ” + friendName
friendName / friendEmail / friendPhonecontact_name / email_from / phone
friendPostCode / friendAddress / friendCityzip / street / city — useful for serviceability checks
referrerName / referrerEmailx_offertown_referrer (custom) — who referred this lead
source_idset to a fixed “Offertown Referral” utm.source, so referral pipeline performance is reportable inside Odoo

Two-way traceability: PATCH the referral’s externalSourceId with the Odoo lead ID after import (see the API reference). The optional capture fields (phone, address, sourceUrl) are present only when the friend provided them on the form. consentAt records the consent checkbox on Offertown-rendered forms; for programmatic captures that omit it, it is the submission timestamp rather than proof of consent.

Flow 2 — report conversions from Odoo

POST/api/v1/partners/referrals/{referralId}/convert

Attach an automated action to whichever Odoo event you treat as the real conversion — for most subscription businesses that’s first invoice paid (account.move reaching payment_state = paid) rather than merely opportunity won. Note the referral field lives on crm.lead: an automation on account.move must traverse back to it (invoice lines → sale order → opportunity_id), or — simpler — propagate x_offertown_referral_id onto sale.order and account.movewhen they’re created. Either way the action then calls:

Request body
{
  "conversionValue": 12999,                  // order value in cents (EUR)
  "currency": "EUR",
  "externalTransactionId": "INV/2026/00042"  // your invoice reference
}
  • externalTransactionId is the idempotency key. Retries with the same ID safely return the original result, so the action can retry on network errors without risking double rewards. Odoo invoice names are only unique per journal, so use a globally unique reference — e.g. prefix with the company or journal, or use the account.move database ID.
  • Reusing a transaction ID against a different referral is rejected with 409 DUPLICATE_CONVERSION.
  • On 429, honor Retry-After and retry — writes are limited to 30 per minute per IP, and conversion reporting to 60 per minute per partner.

What happens next — reward approval, maturation, and billing — is described under money flow in the overview. Conversions you report land as pending rewards that you approve in the partner dashboard before anything is charged.

Capturing leads on your own Odoo website

POST/api/v1/partners/referrals

If you host the referral signup form yourself (for example an Odoo website form), configure your program’s partner-hosted signup URL in the dashboard: referral links then redirect to your page with ?ref_code=… attached. Capture the code with the form and register the lead server-side:

Request body
{
  "referrerIdentifier": "a1b2c3d4",   // the ref_code from the URL
  "friendEmail": "ana@example.com",
  "friendName": "Ana",
  "externalSourceId": "odoo-lead-4211" // your crm.lead ID, for traceability
}

Copy the referralIdfrom the response into the lead’s x_offertown_referral_id— Flow 2 needs it to report the conversion later. This replaces Flow 1 for leads you capture yourself: the referral is created attributed and already in your CRM. Partners using the embeddable widgetor Offertown-hosted forms instead pick leads up via Flow 1 polling.

Testing the loop end-to-end

  1. Create a test referral through your capture path (widget, hosted form, or the create endpoint).
  2. Wait for (or manually trigger) the sync cron — the lead appears in Odoo. (Self-captured leads from the create endpoint are already there.)
  3. Mark it converted in Odoo (pay a test invoice) — the automated action fires.
  4. Confirm the referral shows converted and a pending reward appears in your partner dashboard.

Full API details

Authentication, rate limits, error shapes, and every endpoint used above are documented in the REST API reference.