Blog · Pinterest and Meta
Pinterest CAPI vs Meta CAPI wants checkout and action_source web, and event_id is required.
Pinterest CAPI vs Meta CAPI is a Purchase that is standard on Meta and custom on Pinterest. Meta event_name Purchase, with value and currency, is what optimization trains on. Pinterest's standard name for a completed transaction is checkout. The tag call is pintrk('track', 'checkout'). The API name is checkout. Purchase is not in the API table. Snap wants PURCHASE. Three spellings, one checkout.
POST https://api.pinterest.com/v5/ad_accounts/{ad_account_id}/events. The path needs the advertiser id. A Meta pixel id on this host is the wrong identifier. Auth is a conversion token from Ads Manager, or an OAuth token with ads:write when you also call other endpoints. The body is data[] of events.
Required on each event: event_name, action_source, event_time, event_id, and user_data. Meta recommends event_id and still accepts a server event without it. Omitting event_id on Pinterest is an error when you are deduping against the tag. Custom names are legal, so a Purchase may not throw an enum error. Unmapped custom events are untracked and cannot be used for reporting or optimization.
checkout is the standard name, and subscription is not subscribe
The API table lists checkout as the transaction event, usable for audiences and conversion reporting. Next to it: add_to_cart, lead, page_visit, signup, and the rest of the enum, including subscribe, view_content, and initiate_checkout. Purchase is absent. If you send Purchase you have left the standard list. You can define a custom event, up to 100 characters, case insensitive, up to 15 types per advertiser id, and map it to a standard event such as CHECKOUT. If you passed the custom name and never mapped it, Ads Manager shows it under custom events that are not tracked.
Pinterest's own batch example sends event_name subscription and event_name checkout, then reports num_events_received 2 and num_events_processed 1. The failed row says the name is invalid and points at subscribe and checkout. subscription is not subscribe. Purchase is the same class of miss. An HTTP 200 on the batch is not a SALES campaign that trained.
The browser tag's standard names are lowercase and, on the tag, often written without the underscores the API uses: pagevisit, checkout, addtocart. Checkout in Meta PascalCase is a custom event on that tag. Two base codes are two page visits. addtocart and checkout need the product ids the catalog feed uses, or catalog ads have nothing to hang on.
web is not website, and the first event_id wins for 48 hours
action_source is app_android, app_ios, web, or offline. It is not device_type. Meta uses website. Snap uses WEB. Pinterest uses web. Copying the Meta spelling fails a vendor that lists web. event_time is Unix seconds, ten digits, so the Meta integer can transfer. Thirteen digits are milliseconds and invalid. Date.now() still has to be floored.
Pinterest keeps the first event and drops duplicates within 48 hours when event_id and event_name match across sources. Meta does the same shape of dedup on event_name plus event_id plus Pixel ID, and the first arrival keeps the value. A GTM variable that calls randomUUID on each read gives the tag and the server two ids, so both checkouts stay. Mint the id on the order and pass it to both.
user_data must include at least em, hashed_maids, or the pair of client_ip_address and client_user_agent. em is SHA-256 of a lowercased email, as a list. IP and user agent stay plaintext. Hashing the IP because a Meta helper hashed em makes the event unmatchable. click_id for web should be the _epik cookie when the epik query param is gone. event_source_url is optional and should keep epik when you have it. A Meta fbc does not fill click_id.
The body that trains
Illustrative Pinterest event. Purchase and website are the Meta spellings of this same checkout.
{
"data": [{
"event_name": "checkout",
"action_source": "web",
"event_time": 1759010400,
"event_id": "order-1842",
"event_source_url": "https://shop.example/thanks",
"user_data": { "em": ["<sha256>"], "client_ip_address": "203.0.113.10", "client_user_agent": "Mozilla/5.0" }
}]
}
Map the custom name before you judge ROAS. A week of Purchase events sitting under untracked custom events will not move a standard checkout campaign. The fix is the mapping, or sending checkout in the first place and using that same string on the tag.
Pixellint is not affiliated with Pinterest or Meta. A pack pass means the artifact has checkout or another supported name, action_source web, a ten-digit event_time, and an event_id. It does not mean Ads Manager attributed the order.
A one-dollar test with the real order id burns the dedup slot
Pinterest keeps the first event whose event_id and event_name match, for 48 hours, and drops the later copy. A sandbox checkout of 1.00 that uses the production order id will be the row that stays. The real total, sent later with the same id, is the duplicate. Meta works the same way on event_name plus event_id plus Pixel ID: the first arrival keeps the value. Google can replace value and currency on a matching transactionId. Pinterest will not. Fix the id, or wait out the window, before you resend the real amount.
event_source_url should keep the epik query when you still have it. When the query is gone, click_id should be the _epik cookie. A redirect that keeps utm_source and drops epik leaves Pinterest with a hashed email and an IP. That can still be a legal user_data, because em alone satisfies the requirement. It is a weaker match than the click token. Capture epik on the landing request and store it on your session the way you store fbclid.
Catalog ads need the product ids on add_to_cart and checkout to be the ids in the feed. An empty contents list can still count as a checkout and then have nothing to attach a creative to. Meta contents and Pinterest contents are both lists of products. Copying the shape is fine only when the ids are the Pinterest feed ids, not a Meta content_id namespace you hoped was universal.
Read processed counts, not the HTTP status
The batch example is the proof. Two events received, one processed, and the message names the legal alternatives. Build the alert on num_events_processed against num_events_received. A 200 with a processed count of zero is the Purchase spelling, or subscription instead of subscribe, sitting in a batch that looked successful in the worker log.
Map a custom name to CHECKOUT before you call the integration done, or send checkout from the start and use that string on pintrk. Case is insensitive for custom names, which is why Purchase and purchase are the same untracked bucket. They are still not checkout until you map them.
Pixellint can reject the Meta spellings when you run the Pinterest pack. It cannot see whether Ads Manager has the mapping. The fixture proves the payload. The ads account proves the mapping. Check both before a QBR that compares Pinterest ROAS to Meta ROAS on a shared Purchase string.
What does not transfer
- Purchase becomes checkout. AddToCart becomes add_to_cart on the API and addtocart on the tag.
- action_source website becomes web.
- event_id is required for tag dedup. Meta only recommends it.
- event_time in seconds can transfer. Thirteen digits cannot.
- The advertiser id is in the Pinterest path. A Meta pixel id is the wrong identifier.
- fbclid does not fill click_id. Use epik or the _epik cookie.
- The first matching event_id and event_name wins for 48 hours. A second UUID is a second checkout.
Sources
Contract pages
The dated argument is above. These pages are the field lists.