Car Image API

Kunder · Car Image API

Slik bygger du inn bilbilder i e-post med signerte URL-er som aldri slutter å virke

Car Image API legger hver kundes første rendering i innboksen med en signert URL som fornyes automatisk: mekanismen, regnestykket og koden for å gjøre det selv.

Problemet: et bilde som må fungere i mars

Hver konto på Car Image API får en kort melding fra Jonathan omtrent en time etter sin første rendering. Det opplagte å legge i den e-posten er selve renderingen: nøyaktig den 2024 Porsche 911 eller 2006 Dodge Charger personen nettopp ba om, som bevis på at integrasjonen fungerte, og som et lite skryt.

E-post er den verst tenkelige flaten for en signert URL. En nettside gjengis på nytt ved hvert besøk; en e-post gjengis én gang og åpnes når leseren kommer til den, en dag, en måned eller et år senere, ofte gjennom Gmails bildeproxy. De signerte leverings-URL-ene API-et allerede tilbød, hadde en maksimal TTL på sju dager, noe som er riktig tak for en nettleser, men som garanterer et ødelagt bilde i innboksen innen uke to. Å legge ved eller bygge inn PNG-en gjør hver e-post unødvendig stor.

Det vi ønsket, var en URL som oppfører seg som et hostet bilde, fortsetter å virke så lenge noen kan tenkes å åpne e-posten, og likevel belaster kontoen rettferdig for det den faktisk leverer.

Løsningen: signerte URL-er som fornyes automatisk

Vi la til ett flagg i POST /api/v1/image-urls: renew: true. En fornybar URL genereres akkurat som alle andre, teller bildet sitt som et kjøretøybilde for måneden og er gyldig i ttl_seconds. Forskjellen er hva som skjer etter TTL-en. I stedet for en 403 fornyer den første innlastingen i hvert nye vindu på ttl_seconds URL-en og leverer bildet. En fornyelse teller bildet én gang i måneden den skjer, og ingenting mer hvis bildet allerede er telt den måneden. Alle videre innlastinger i det vinduet kan mellomlagres offentlig, akkurat som i det første vinduet. Slik fortsetter det frem til renews_until, opptil ett år frem i tid.

Tre egenskaper fulgte av den utformingen, og hver av dem var viktig for e-post:

  • Ingenting å sende eller generere på nytt. URL-en i e-posten er URL-en for alltid. Ingen cron-jobb som skriver om lagrede lenker, ingen ny e-post med et ferskt bilde.
  • Tell åpninger, ikke tid. Et vindu som ingen åpner, teller ingenting. En e-post som leses av én person på én dag, tilsvarer det ene kjøretøybildet den ble generert for. En e-post som åpnes hver uke i et år, teller bildet én gang i hver måned den åpnes, maks tolv ganger.
  • Idempotent telling. Hvert vindu registreres én gang, med nøkkelen renew:<url id>:<window>, unik per URL og vindu. Femti åpninger på en uke, eller to e-postproxyer som kappes om den første åpningen, telles én gang.

Livssyklus-e-postene lager disse URL-ene gjennom samme kodesti som det offentlige endepunktet bruker, som plattformtokener: knyttet til ingen API-nøkkel og aldri fakturert, fordi de er våre, men levert av den samme GET /api/v1/delivery/{token}-ruten, med de samme sjudagersvinduene og den samme hurtigbufringen. Bildet i e-posten om første rendering er produktet som demonstrerer seg selv.

Generer én fornybar URL for kundens første gjengivelse
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…"
}

Selve e-posten

Malen er laget med React Email med innebygde stiler, fordi e-postklienter fjerner stilark. Renderingen ligger i en tabellcelle med kantlinje på en dempet bakgrunn, hentet i 480 piksler og vist i 240 slik at den holder seg skarp på retina-skjermer, med en etikett over og to bildetekstlinjer under. Transparent PNG er hele poenget med produktet, så vi beholder det; i en gammel Outlook som gjør alfakanalen svart, er en format: "jpg"-rendering på en ensfarget cellebakgrunn reserveløsningen.

Kortet, som ren 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>

Alt annet i meldingen er tekst: hva URL-en er, hvorfor den fortsetter å virke, nøyaktig hvilken POST som lager en for deres eget kjøretøy, og en lenke til denne siden. E-posten har en avmeldingslenke og List-Unsubscribe-headerne, og hver produktlenke er merket slik at vi i anskaffelsesrapporten kan se om historien du leser, har fått noen til å komme tilbake.

Gjør det selv i tre steg

  1. Generer på serversiden når du bygger e-posten. Ett kall per kjøretøy, eller opptil femti per kall for en oppsummering. Lagre url og renews_until sammen med meldingen.
  2. Legg URL-en i en <img> med bredde, høyde og alt-tekst. Alt-teksten navngir kjøretøyet («2024 Porsche 911, rød, skrått forfra»), ikke «bil».
  3. Sørg for at kontoen har dekning. En fornyelse teller bildet én gang i måneden den faller i. Hvis planens kjøretøybilder er brukt opp, svarer den 402 til kvoten nullstilles den 1., så tilpass planen til antall bilder du leverer.
Med TypeScript-SDK-et
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

Den fullstendige parameterreferansen, hurtigbufferhoder og feilkoder finner du i dokumentasjonen for signerte URL-er. Agentferdigheten som følger med pluginen, kjenner de samme reglene, så en assistent som blir bedt om å «legge denne bilen i nyhetsbrevet», lager en fornybar URL i stedet for å lime inn en nøkkel i en mal.

Ofte stilte spørsmål

Hvorfor ikke legge ved bildet eller bygge det inn som base64?
Vedlegg og base64 gjør hver melding unødvendig stor. En signert URL er noen hundre byte og lastes gjennom e-postklientens bildeproxy som et hvilket som helst annet nettbasert bilde.
Hva koster en URL som fornyes automatisk?
Ett av månedens kjøretøybilder når det opprettes, deretter telles det samme bildet én gang i hver senere måned der et fornyelsesvindu faktisk åpnes, frem til renews_until; en måned der ingen åpner e-posten, teller ingenting. Pro, til 49 USD i måneden, inkluderer 2 500 kjøretøybilder i måneden.
Hva skjer når månedens kjøretøybilder er brukt opp?
Innlastingen svarer 402, og bildet vises som ødelagt til månedens kvote nullstilles eller planen oppgraderes; selve URL-en forblir gyldig og fungerer igjen ved neste innlasting. Et bilde som allerede er telt denne måneden, vises fortsatt.
Fungerer dette i Gmail, Outlook og Apple Mail?
Ja. Leveringsendepunktet er en vanlig offentlig GET med Cache-Control, en ETag og CORS-headere, som er nøyaktig det bildeproxyer forventer. PNG-gjennomsiktighet vises i alle nåværende klienter; for svært gamle Outlook-versjoner bør du be om format jpg på ensfarget bakgrunn.
Kan en URL tilbakekalles?
Tilbakekall API-nøkkelen som genererte den, så svarer alle URL-er fra den nøkkelen med 403 ved neste innlasting, fornyelser inkludert. Delte hurtigbuffere fortsetter å levere i maks én time etter det.