From f947451ae219f22b62feb26eca40ed3f969d7e80 Mon Sep 17 00:00:00 2001 From: utkuufuk Date: Fri, 13 Nov 2026 14:07:58 +0300 Subject: [PATCH] feat(targeting-client): recipient created_at (ER-5515) Regenerated from the deployed Targeting API spec plus the recipient's created_at from targeting-api!105, which isn't deployed yet: when the entity became a recipient, shown as the "Added" column in the campaign recipients table. Also syncs the already deployed CampaignType, setupCampaign target_ids and changeCampaignStatus docs. Co-Authored-By: Claude Opus 5.5 --- .../targeting-client-recipient-created-at.md | 5 ++ clients/targeting-client/src/openapi.d.ts | 55 +++++++++++++++---- clients/targeting-client/src/openapi.json | 30 ++++++++-- 3 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 .changeset/targeting-client-recipient-created-at.md diff --git a/.changeset/targeting-client-recipient-created-at.md b/.changeset/targeting-client-recipient-created-at.md new file mode 100644 index 00000000..8f18700b --- /dev/null +++ b/.changeset/targeting-client-recipient-created-at.md @@ -0,0 +1,5 @@ +--- +"@epilot/targeting-client": minor +--- + +Regenerate types from the Targeting API: a campaign recipient gets `created_at`, when the entity became a recipient (at launch, when it first saw the campaign in a portal or as a Next Best Action, or when the daily recipient check of a campaign with `auto_add_recipients` added it; ER-5515). Also syncs what's already deployed: the `CampaignType` enum with `product_recommendations` and `type` on the campaign, `setupCampaign` requiring exactly one `campaign.target_ids` entry, and `changeCampaignStatus` documenting `CAMPAIGN_HAS_NO_PRODUCT_RECOMMENDATIONS`. diff --git a/clients/targeting-client/src/openapi.d.ts b/clients/targeting-client/src/openapi.d.ts index e833403b..13ab6ee5 100644 --- a/clients/targeting-client/src/openapi.d.ts +++ b/clients/targeting-client/src/openapi.d.ts @@ -348,6 +348,8 @@ declare namespace Components { flow_id?: string; job_id?: string; target?: BaseRelation; + product_recommendations?: BaseRelation; + type?: /* Use case of a campaign. Set by campaign setup. */ CampaignType; } /** * Lifecycle status of a campaign. @@ -361,6 +363,10 @@ declare namespace Components { * */ export type CampaignStatus = "draft" | "scheduled" | "activating" | "active" | "inactive"; + /** + * Use case of a campaign. Set by campaign setup. + */ + export type CampaignType = "tariff_change"; /** * Describes the structure of a client error response, which can be one of several types: * 1. `MessageError`: Contains a 'message' field for general descriptive errors. @@ -1750,6 +1756,13 @@ declare namespace Components { url: string; clicked_at: string; // date-time }[]; + /** + * When the entity became a recipient of the campaign: at launch, when it first saw the + * campaign in a portal or as a Next Best Action, or when the daily recipient check added it + * (campaigns with `auto_add_recipients` on). + * + */ + created_at?: string; // date-time updated_at?: string; // date-time } export interface RetriggerAutomationsRequest { @@ -1789,6 +1802,9 @@ declare namespace Components { */ SetupTariffChangeCampaignRequest; export interface SetupTariffChangeCampaignRequest { + /** + * The `CampaignType` of this variant. + */ type: "tariff_change"; product_recommendation: { /** @@ -1846,16 +1862,19 @@ declare namespace Components { name: string; goal?: string; /** - * List of target entity IDs to attach to the campaign. Today only a single - * entry is supported (campaign.target is has_one) but the array shape is kept - * for forward-compatibility — only `target_ids[0]` is used. + * The campaign's audience as a list with exactly one target entity ID. A campaign has + * exactly one audience (`campaign.target` is has_one); the array shape is kept for + * compatibility. A request with no or more than one entry is rejected with 400 and + * nothing is created; extra entries are never silently dropped. * */ - target_ids: /** - * example: - * b8c01433-5556-4e2b-aad4-6f5348d1df84 - */ - BaseUUID /* uuid */[]; + target_ids: [ + /** + * example: + * b8c01433-5556-4e2b-aad4-6f5348d1df84 + */ + BaseUUID /* uuid */ + ]; /** * Optional start of the campaign. Launching the campaign before this time schedules it, and * it starts on its own at this time. Without it, the campaign starts when it is launched. @@ -1940,6 +1959,9 @@ declare namespace Components { }; } export interface SetupTariffChangeCampaignResponse { + /** + * The `CampaignType` of this variant. + */ type: "tariff_change"; product_recommendation_id: /** * example: @@ -2423,7 +2445,9 @@ export interface OperationMethods { * * Only launching needs a target and a delivery method (an automation flow, a portal block or a valid * Next Best Action); otherwise it is rejected with 409 `CAMPAIGN_HAS_NO_TARGET` or - * `CAMPAIGN_HAS_NO_DELIVERY_METHOD`. Cancelling, stopping and resetting work without them. + * `CAMPAIGN_HAS_NO_DELIVERY_METHOD`. A `tariff_change` campaign also needs at least one linked product + * recommendation (409 `CAMPAIGN_HAS_NO_PRODUCT_RECOMMENDATIONS`), checked again when a scheduled campaign + * starts on its own. Cancelling, stopping and resetting work without them. * * Status transition is accompanied by side effects, e.g., automation execution. * @@ -2485,6 +2509,10 @@ export interface OperationMethods { * `CAMPAIGN_END_BEFORE_START` or `CAMPAIGN_END_IN_PAST` when the dates could not be launched, and * nothing is created. * + * A campaign has exactly one audience: `campaign.target_ids` must contain exactly one target ID. + * A request with no or more than one entry fails request validation with 400 (the error points at + * `/requestBody/campaign/target_ids`), and nothing is created. + * */ 'setupCampaign'( parameters?: Parameters | null, @@ -2676,7 +2704,9 @@ export interface PathsDictionary { * * Only launching needs a target and a delivery method (an automation flow, a portal block or a valid * Next Best Action); otherwise it is rejected with 409 `CAMPAIGN_HAS_NO_TARGET` or - * `CAMPAIGN_HAS_NO_DELIVERY_METHOD`. Cancelling, stopping and resetting work without them. + * `CAMPAIGN_HAS_NO_DELIVERY_METHOD`. A `tariff_change` campaign also needs at least one linked product + * recommendation (409 `CAMPAIGN_HAS_NO_PRODUCT_RECOMMENDATIONS`), checked again when a scheduled campaign + * starts on its own. Cancelling, stopping and resetting work without them. * * Status transition is accompanied by side effects, e.g., automation execution. * @@ -2746,6 +2776,10 @@ export interface PathsDictionary { * `CAMPAIGN_END_BEFORE_START` or `CAMPAIGN_END_IN_PAST` when the dates could not be launched, and * nothing is created. * + * A campaign has exactly one audience: `campaign.target_ids` must contain exactly one target ID. + * A request with no or more than one entry fails request validation with 400 (the error points at + * `/requestBody/campaign/target_ids`), and nothing is created. + * */ 'post'( parameters?: Parameters | null, @@ -2960,6 +2994,7 @@ export type BaseTags = Components.Schemas.BaseTags; export type BaseUUID = Components.Schemas.BaseUUID; export type Campaign = Components.Schemas.Campaign; export type CampaignStatus = Components.Schemas.CampaignStatus; +export type CampaignType = Components.Schemas.CampaignType; export type ClientError = Components.Schemas.ClientError; export type CreateRecipientPayload = Components.Schemas.CreateRecipientPayload; export type DiscoverCampaignsParams = Components.Schemas.DiscoverCampaignsParams; diff --git a/clients/targeting-client/src/openapi.json b/clients/targeting-client/src/openapi.json index 640b90e3..f86d56c5 100644 --- a/clients/targeting-client/src/openapi.json +++ b/clients/targeting-client/src/openapi.json @@ -38,7 +38,7 @@ "post": { "operationId": "changeCampaignStatus", "summary": "changeCampaignStatus", - "description": "Moves a campaign to its next status, depending on its current one:\n\n- `draft`: launches the campaign. With a `start_date` still in the future it becomes `scheduled` and\n starts on its own at that time; otherwise it starts now (`activating`, then `active`). Rejected with\n 400 if the dates are invalid: `INVALID_CAMPAIGN_DATES` (unparsable), `CAMPAIGN_END_BEFORE_START`\n or `CAMPAIGN_END_IN_PAST`.\n- `scheduled`: cancels the schedule; the campaign goes back to `draft` and keeps its dates.\n- `active`: stops the campaign (`inactive`) and sets `end_date` to now.\n- `inactive`: resets the campaign to `draft` and clears its `start_date` and `end_date`: they\n recorded the previous run, and a past end date would block launching it again.\n\nOnly launching needs a target and a delivery method (an automation flow, a portal block or a valid\nNext Best Action); otherwise it is rejected with 409 `CAMPAIGN_HAS_NO_TARGET` or\n`CAMPAIGN_HAS_NO_DELIVERY_METHOD`. Cancelling, stopping and resetting work without them.\n\nStatus transition is accompanied by side effects, e.g., automation execution.\n", + "description": "Moves a campaign to its next status, depending on its current one:\n\n- `draft`: launches the campaign. With a `start_date` still in the future it becomes `scheduled` and\n starts on its own at that time; otherwise it starts now (`activating`, then `active`). Rejected with\n 400 if the dates are invalid: `INVALID_CAMPAIGN_DATES` (unparsable), `CAMPAIGN_END_BEFORE_START`\n or `CAMPAIGN_END_IN_PAST`.\n- `scheduled`: cancels the schedule; the campaign goes back to `draft` and keeps its dates.\n- `active`: stops the campaign (`inactive`) and sets `end_date` to now.\n- `inactive`: resets the campaign to `draft` and clears its `start_date` and `end_date`: they\n recorded the previous run, and a past end date would block launching it again.\n\nOnly launching needs a target and a delivery method (an automation flow, a portal block or a valid\nNext Best Action); otherwise it is rejected with 409 `CAMPAIGN_HAS_NO_TARGET` or\n`CAMPAIGN_HAS_NO_DELIVERY_METHOD`. A `tariff_change` campaign also needs at least one linked product\nrecommendation (409 `CAMPAIGN_HAS_NO_PRODUCT_RECOMMENDATIONS`), checked again when a scheduled campaign\nstarts on its own. Cancelling, stopping and resetting work without them.\n\nStatus transition is accompanied by side effects, e.g., automation execution.\n", "tags": [ "Campaign" ], @@ -181,7 +181,7 @@ "post": { "operationId": "setupCampaign", "summary": "setupCampaign", - "description": "Creates a `campaign` entity together with its related entities and configurations in a single call.\nUsed by the campaign wizard UI, but not restricted to it.\n\nThe campaign is created as a `draft`. Its optional `start_date` and `end_date` take effect when it is\nlaunched (see `changeCampaignStatus`). Returns 400 with `INVALID_CAMPAIGN_DATES`,\n`CAMPAIGN_END_BEFORE_START` or `CAMPAIGN_END_IN_PAST` when the dates could not be launched, and\nnothing is created.\n", + "description": "Creates a `campaign` entity together with its related entities and configurations in a single call.\nUsed by the campaign wizard UI, but not restricted to it.\n\nThe campaign is created as a `draft`. Its optional `start_date` and `end_date` take effect when it is\nlaunched (see `changeCampaignStatus`). Returns 400 with `INVALID_CAMPAIGN_DATES`,\n`CAMPAIGN_END_BEFORE_START` or `CAMPAIGN_END_IN_PAST` when the dates could not be launched, and\nnothing is created.\n\nA campaign has exactly one audience: `campaign.target_ids` must contain exactly one target ID.\nA request with no or more than one entry fails request validation with 400 (the error points at\n`/requestBody/campaign/target_ids`), and nothing is created.\n", "tags": [ "Campaign" ], @@ -1032,11 +1032,24 @@ }, "target": { "$ref": "#/components/schemas/BaseRelation" + }, + "product_recommendations": { + "$ref": "#/components/schemas/BaseRelation" + }, + "type": { + "$ref": "#/components/schemas/CampaignType" } } } ] }, + "CampaignType": { + "type": "string", + "description": "Use case of a campaign. Set by campaign setup.", + "enum": [ + "tariff_change" + ] + }, "Target": { "allOf": [ { @@ -1571,6 +1584,11 @@ } } }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When the entity became a recipient of the campaign: at launch, when it first saw the\ncampaign in a portal or as a Next Best Action, or when the daily recipient check added it\n(campaigns with `auto_add_recipients` on).\n" + }, "updated_at": { "type": "string", "format": "date-time" @@ -1771,6 +1789,7 @@ "properties": { "type": { "type": "string", + "description": "The `CampaignType` of this variant.", "enum": [ "tariff_change" ] @@ -1854,10 +1873,12 @@ }, "target_ids": { "type": "array", - "description": "List of target entity IDs to attach to the campaign. Today only a single\nentry is supported (campaign.target is has_one) but the array shape is kept\nfor forward-compatibility — only `target_ids[0]` is used.\n", + "description": "The campaign's audience as a list with exactly one target entity ID. A campaign has\nexactly one audience (`campaign.target` is has_one); the array shape is kept for\ncompatibility. A request with no or more than one entry is rejected with 400 and\nnothing is created; extra entries are never silently dropped.\n", "items": { "$ref": "#/components/schemas/BaseUUID" - } + }, + "minItems": 1, + "maxItems": 1 }, "start_date": { "type": "string", @@ -1944,6 +1965,7 @@ "properties": { "type": { "type": "string", + "description": "The `CampaignType` of this variant.", "enum": [ "tariff_change" ]