---
title: "Create custom conversion"
method: POST
path: "/v1/ads/conversions/custom-conversions"
tags: ["Conversions"]
---

# Create custom conversion

`POST /v1/ads/conversions/custom-conversions`

## Request

- Base URL: `https://zernio.com/api`
- URL: `https://zernio.com/api/v1/ads/conversions/custom-conversions`
- Auth: HTTP bearer

Creates a Meta custom conversion for ads to optimise toward, reusing an existing one with the same name and pixel.

It provisions the Meta custom conversion an ads flow optimises toward, and hands back the `customConversionId` for `promotedObject.customConversionId` on POST /v1/ads/create. This removes the manual "create it in Ads Manager first" step.

### Reuse is ours, not Meta's

Meta's create is not idempotent, so a retried request would otherwise mint a duplicate carrying none of the original's optimisation history.

A non-archived conversion with the same `name` on the same `pixelId` is returned instead of created, with `reused: true` and a 200 rather than a 201.

### Rule

`rule` is forwarded verbatim in Meta's own grammar (e.g. `{"url": {"i_contains": "thank-you"}}`). Meta validates it and rejects a malformed one with "A conversion rule is required at creation time".

## Request body

- object
  - `accountId` string, required: The connected ads account (SocialAccount ID).
  - `adAccountId` string, required: Platform ad account id (Meta act_<n>, Google customer id, LinkedIn account id, ...).
  - `name` string, required: Also the reuse key, together with pixelId.
  - `pixelId` string, required: Meta pixel id (event_source_id). From GET /v1/accounts/{accountId}/tracking-tags.
  - `customEventType` string, required: Meta custom_event_type, e.g. LEAD, PURCHASE, OTHER.
  - `rule` object, required: Meta conversion rule, forwarded verbatim.

## Response `200`

An existing custom conversion was reused

- CustomConversionResult
  - `adAccountId` string
  - `customConversionId` string: Drops straight into promotedObject.customConversionId on POST /v1/ads/create.
  - `reused` boolean: True when an existing conversion matched name + pixelId; the response is then a 200.
  - `customConversion` CustomConversion
    - `id` string
    - `name` string, nullable
    - `rule` object, nullable: Meta's rule, parsed back from the string Meta stores.
    - `customEventType` string, nullable
    - `pixelId` string, nullable: Meta's event_source_id, the pixel the rule reads from.
    - `isArchived` boolean
    - `defaultConversionValue` number, nullable: Value Meta assigns a conversion that carries none, in the ad account's currency.

## Other responses

- `201`: Custom conversion created
- `400`: Invalid input, or Meta rejected the conversion (bad rule, per-account cap reached)
- `401`: Missing or invalid API key. `code` is `missing_credentials` when no Authorization header was sent and `invalid_credentials` when the key is unknown, revoked or expired.
- `403`: Ads access required, or the token lacks the ads permissions. Also returned with code `ad_account_not_selected` when the connection has selected ad accounts and the ad account this request targets is not among them. `details` carries `accountId`, `adAccountId` and `selectedAdAccountIds`. To fix it, add the ad account to the selection (GET /v1/connect/{platform}/ads with adAccountIds, which replaces the selection) or use a connection that has it selected.
- `404`: The account or requested resource was not found or is not accessible. An account ID may have been disconnected and removed. Read GET /v1/accounts for current account IDs.
- `409`: The account exists but is inactive or needs reconnection. Reconnect it, then read GET /v1/accounts for its current account ID before retrying. Code: ads_connection_required.

## Changes

- **2026-11-11** `34f8dbff5e0d`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/ads/conversions/custom-conversions/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) - [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/21ba7421089d?raw)
