Car Image API

Zákazníci · Car Image API

Jak vkládat obrázky aut do e-mailů pomocí podepsaných URL, které nikdy nepřestanou fungovat

Car Image API doručí každému zákazníkovi jeho první render do schránky s automaticky obnovovanou podepsanou URL: mechanismus, výpočty a kód, jak to udělat sami.

Problém: obrázek, který musí fungovat i v březnu

Každý účet v Car Image API dostane zhruba hodinu po prvním renderu krátkou zprávu od Jonathana. Nejpřirozenější je dát do takového e-mailu samotný render: přesně to Porsche 911 z roku 2024 nebo Dodge Charger z roku 2006, o které si dotyčný právě řekl, jako důkaz, že integrace funguje, a jako malou chloubu.

E-mail je pro podepsanou URL to nejhorší možné prostředí. Stránka se vykresluje znovu při každé návštěvě; e-mail se vykreslí jednou a otevře se, kdykoli se k němu čtenář dostane, za den, za měsíc nebo za rok, často přes proxy obrázků Gmailu. Podepsané doručovací URL, které API už nabízelo, měly maximální TTL sedm dní, což je pro prohlížeč správný strop, ale v doručené poště to nejpozději ve druhém týdnu zaručuje nefunkční obrázek. Přikládání PNG nebo jeho vkládání přímo do zprávy nafukuje každý e-mail.

Chtěli jsme URL, která se chová jako hostovaný obrázek, funguje tak dlouho, dokud by někdo mohl e-mail otevřít, a přesto účet férově zatěžuje jen za to, co skutečně doručí.

Řešení: automaticky obnovované podepsané URL

Do POST /api/v1/image-urls jsme přidali jeden příznak: renew: true. Obnovitelná URL se vytváří stejně jako každá jiná, započítá svůj obrázek jako obrázek vozidla daného měsíce a platí po dobu ttl_seconds. Rozdíl je v tom, co se stane po uplynutí TTL. Místo chyby 403 první načtení v každém novém okně o délce ttl_seconds URL obnoví a obrázek zobrazí; obnovení započítá obrázek jednou v měsíci, do kterého spadá, a nic dalšího, pokud už byl v daném měsíci započítán. Každé další načtení v tomto okně lze veřejně cachovat, stejně jako v prvním okně. Tak to pokračuje až do renews_until, nejvýše rok dopředu.

Z tohoto návrhu vyplynuly tři vlastnosti a každá z nich byla pro e-mail důležitá:

  • Nic není třeba znovu posílat ani generovat. URL v e-mailu zůstává navždy stejná. Žádná úloha cron přepisující uložené odkazy, žádný druhý e-mail s novým obrázkem.
  • Počítají se otevření, ne čas. Okno, které nikdo neotevře, se vůbec nezapočítá. E-mail, který si jeden člověk přečte v jeden den, představuje jeden obrázek vozidla, pro který byl vytvořen; e-mail otevíraný každý týden po celý rok započítá tento obrázek jednou v každém měsíci, kdy je otevřen, tedy nejvýše dvanáctkrát.
  • Idempotentní počítání. Každé okno se zaznamená jednou pod klíčem renew:<url id>:<window>, jedinečným pro každou URL a okno. Padesát otevření za týden nebo dvě poštovní proxy, které se předhánějí při prvním otevření, se započítají jednou.

E-maily životního cyklu generují tyto URL stejnou cestou v kódu, jakou používá veřejný endpoint, jako platformní tokeny: nejsou vázané na žádný klíč API a nikdy se neúčtují, protože jsou naše, ale obsluhuje je identická trasa GET /api/v1/delivery/{token} se stejnými sedmidenními okny a stejným cachováním. Obrázek v e-mailu o prvním renderu je produkt, který předvádí sám sebe.

Vygenerujte jednu obnovitelnou URL pro první render zákazníka
curl -X POST https://carimage.dev/api/v1/image-urls \
  -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"images":[{"make":"porsche","model":"911","year":2024,"view":"front-3-4","color":"red","width":480}],"ttl_seconds":604800,"renew":true}'
201 Created
{
  "data": [
    {
      "id": "3f0c2a7e-1c1e-4c2a-9c39-4f1f0a4b2d10",
      "url": "https://carimage.dev/api/v1/delivery/eyJhbGciOi…",
      "expires_at": "2026-09-21T09:00:00.000Z",
      "max_uses": 0,
      "renews_until": "2027-09-14T09:00:00.000Z",
      "vehicle": {
        "make": "porsche",
        "model": "911",
        "year": 2024,
        "view": "front-3-4",
        "color": "red",
        "width": 480,
        "format": "png"
      }
    }
  ],
  "billing": {
    "charged_on": "creation",
    "credits_charged": 1,
    "credits_remaining": 4869,
    "credits_per_url": 1,
    "renewal": {
      "window_seconds": 604800,
      "credits_per_window": 1,
      "until": "2027-09-14T09:00:00.000Z"
    }
  },
  "request_id": "req_01j9x…"
}

Samotný e-mail

Šablona je postavená na React Email s inline styly, protože poštovní klienti odstraňují šablony stylů. Render je umístěn v buňce tabulky s okrajem na jemném pozadí, vyžádaný v šířce 480 px a zobrazený v šířce 240 px, aby zůstal ostrý na displejích retina, s odznakem nad ním a dvěma řádky popisku pod ním. Průhledné PNG je hlavním smyslem produktu, takže ho ponecháváme; pro starý Outlook, který vykresluje alfa kanál černě, slouží jako záloha render format: "jpg" na plném pozadí buňky.

Karta jako prosté HTML
<!-- inline styles only: mail clients strip stylesheets -->
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
  <tr>
    <td align="center" style="padding:24px;background:#fafaf9;border:1px solid #e7e5e4;border-radius:16px;">
      <img
        src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…"
        alt="2024 Porsche 911, red, front three-quarter view"
        width="240" height="240"
        style="display:block;margin:0 auto;max-width:100%;height:auto;"
      />
      <p style="margin:14px 0 2px;font:700 18px/26px -apple-system,Segoe UI,Roboto,sans-serif;color:#1c1917;">2024 Porsche 911</p>
      <p style="margin:0;font:13px/20px ui-monospace,Menlo,monospace;color:#78716c;">Front three-quarter · Red</p>
    </td>
  </tr>
</table>

Vše ostatní ve zprávě je text: co je ta URL, proč stále funguje, přesný POST požadavek, kterým si ji vytvoří pro vlastní vozidlo, a odkaz na tuto stránku. E-mail obsahuje odkaz pro odhlášení a hlavičky List-Unsubscribe a každý odkaz na produkt je označen, takže v reportu akvizice vidíme, zda příběh, který právě čtete, někoho přivedl zpět.

Udělejte si to sami ve třech krocích

  1. Vytvářejte je na serveru při sestavování e-mailu. Jedno volání na vozidlo, nebo až padesát v jednom volání pro souhrnný e-mail. Uložte url a renews_until spolu se zprávou.
  2. Vložte URL do <img> se šířkou, výškou a alternativním textem. Alternativní text pojmenovává vozidlo („2024 Porsche 911, červené, pohled zepředu ze tří čtvrtin“), nikoli „auto“.
  3. Mějte účet zajištěný. Obnovení započítá obrázek jednou v měsíci, do kterého spadne; pokud jsou obrázky vozidel z tarifu vyčerpány, vrací 402, dokud se limit 1. dne v měsíci neobnoví, proto tarif dimenzujte podle počtu obrázků, které doručujete.
S TypeScript SDK
import { CarImageClient } from "@meterapp/car-image-sdk";

const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });

// One call per email: the vehicle the person rendered, at 2x the display width.
const { data } = await client.createImageUrls(
  [{ make: "porsche", model: "911", year: 2024, view: "front-3-4", color: "red", width: 480 }],
  { ttlSeconds: 604_800, renew: true, renewDays: 365 }
);
const src = data[0].url; // drop into <img src>, store data[0].renews_until next to it

Úplný přehled parametrů, hlavičky pro cache a chybové kódy najdete v dokumentaci k podepsaným URL. Agentní skill dodávaný s pluginem zná stejná pravidla, takže asistent požádaný, aby „dal tohle auto do newsletteru“, vytvoří obnovitelnou URL, místo aby vložil klíč do šablony.

Často kladené otázky

Proč obrázek nepřiložit jako přílohu nebo ho nevložit přímo jako base64?
Přílohy a base64 nafukují každou zprávu. Podepsaná URL má pár set bajtů a načítá se přes obrázkovou proxy poštovního klienta jako jakýkoli hostovaný obrázek.
Kolik stojí automaticky obnovovaná URL adresa?
Jeden obrázek vozidla z měsíčního limitu při vytvoření, poté se stejný obrázek započítá jednou v každém dalším měsíci, ve kterém se skutečně otevře okno obnovení, až do renews_until; měsíc, ve kterém e-mail nikdo neotevře, se nepočítá. Pro za 49 US$ měsíčně zahrnuje 2 500 obrázků vozidel měsíčně.
Co se stane, když se obrázky vozidel na daný měsíc vyčerpají?
Načtení vrátí 402 a obrázek se zobrazí jako nefunkční, dokud se měsíční limit neobnoví nebo nepřejdete na vyšší tarif; samotná URL zůstává platná a při dalším načtení opět funguje. Obrázek, který už byl tento měsíc započítán, se zobrazuje dál.
Funguje to v Gmailu, Outlooku a Apple Mailu?
Ano. Doručovací endpoint je obyčejný veřejný GET s hlavičkami Cache-Control, ETag a CORS, což je přesně to, co obrázkové proxy očekávají. Průhlednost PNG se zobrazí ve všech současných klientech; pro velmi staré verze Outlooku si vyžádejte formát jpg s plným pozadím.
Lze URL zneplatnit?
Zrušte API klíč, kterým byla URL vytvořena, a každá URL z tohoto klíče při příštím načtení vrátí 403, a to včetně obnovených. Sdílené mezipaměti ji poté budou poskytovat nejvýše hodinu.