2191 lines
67 KiB
TypeScript
2191 lines
67 KiB
TypeScript
import type { ApiSettings, CampaignListItem, DeltaDeletedItem } from "../types";
|
|
import { apiDownload, apiFetch } from "./client";
|
|
import {
|
|
apiReferenceOptionProvider,
|
|
type ReferenceOptionProvider
|
|
} from "@govoplan/core-webui";
|
|
import { campaignJobsQueryParams, type CampaignJobsQueryParameters } from "../features/campaigns/utils/jobListQuery";
|
|
import { campaignVersionUpdateForRequest } from "../features/campaigns/utils/editorState";
|
|
export {
|
|
fetchResourceAccessExplanation,
|
|
fetchResourceAccessExplanationSubjects
|
|
} from "@govoplan/core-webui";
|
|
export type {
|
|
AccessDecisionProvenanceItem,
|
|
ResourceAccessExplanationUser as AccessExplanationUser,
|
|
ResourceAccessExplanationResponse,
|
|
ResourceAccessExplanationSubjectsResponse
|
|
} from "@govoplan/core-webui";
|
|
|
|
export type CampaignListResponse =
|
|
CampaignListItem[] |
|
|
{
|
|
campaigns?: CampaignListItem[];
|
|
items?: CampaignListItem[];
|
|
results?: CampaignListItem[];
|
|
};
|
|
|
|
|
|
|
|
export type CampaignShare = {
|
|
id: string;
|
|
campaign_id: string;
|
|
target_type: "user" | "group";
|
|
target_id: string;
|
|
permission: "read" | "write";
|
|
revoked_at?: string | null;
|
|
};
|
|
|
|
export type CampaignShareTarget = {id: string;name: string;secondary?: string | null;};
|
|
export type CampaignShareTargets = {users: CampaignShareTarget[];groups: CampaignShareTarget[];};
|
|
|
|
export type CampaignCollaborationReferenceKind =
|
|
| "campaign_version"
|
|
| "recipient_import_batch"
|
|
| "attachment_rule"
|
|
| "delivery_job"
|
|
| "report";
|
|
|
|
export type CampaignCollaborationReference = {
|
|
kind: CampaignCollaborationReferenceKind;
|
|
id: string;
|
|
label?: string | null;
|
|
};
|
|
|
|
export type CampaignCollaborationEntry = {
|
|
id: string;
|
|
campaign_id: string;
|
|
actor_user_id?: string | null;
|
|
actor_label: string;
|
|
visibility: "collaborators" | "moderators";
|
|
content?: string | null;
|
|
content_sha256: string;
|
|
mention_user_ids: string[];
|
|
reference?: CampaignCollaborationReference | null;
|
|
tombstone?: "withdrawn" | "redacted" | null;
|
|
tombstone_reason?: string | null;
|
|
withdrawn_at?: string | null;
|
|
redacted_at?: string | null;
|
|
created_at: string;
|
|
};
|
|
|
|
export type CampaignCollaborationListResponse = {
|
|
items: CampaignCollaborationEntry[];
|
|
next_cursor?: string | null;
|
|
has_more: boolean;
|
|
};
|
|
|
|
export type CampaignCollaborationCreate = {
|
|
content: string;
|
|
visibility?: CampaignCollaborationEntry["visibility"];
|
|
reference?: Pick<CampaignCollaborationReference, "kind" | "id"> | null;
|
|
mention_user_ids?: string[];
|
|
};
|
|
|
|
export type CampaignWorkAssigneeType = "account" | "group" | "organization_function";
|
|
export type CampaignWorkAssignmentStatus = "open" | "in_progress" | "completed" | "rejected" | "cancelled";
|
|
export type CampaignWorkAssignmentResolutionState = "resolved" | "unavailable" | "provider_unavailable";
|
|
|
|
export type CampaignWorkAssignment = {
|
|
id: string;
|
|
campaign_id: string;
|
|
purpose: string;
|
|
status: CampaignWorkAssignmentStatus;
|
|
due_at?: string | null;
|
|
assignee_type: CampaignWorkAssigneeType;
|
|
assignee_id: string;
|
|
assignee_label_snapshot: string;
|
|
assignee_current_label?: string | null;
|
|
assignee_resolution_state: CampaignWorkAssignmentResolutionState;
|
|
resolution_provenance: Record<string, unknown>;
|
|
resolution_checked_at: string;
|
|
assigned_by_user_id?: string | null;
|
|
assigned_by_label: string;
|
|
reference?: CampaignCollaborationReference | null;
|
|
completed_at?: string | null;
|
|
cancelled_at?: string | null;
|
|
task_mirror_id?: string | null;
|
|
task_mirror_status: "not_configured" | "mirrored" | "failed" | "skipped";
|
|
task_mirror_error?: string | null;
|
|
resource_revision: number;
|
|
created_at: string;
|
|
updated_at: string;
|
|
};
|
|
|
|
export type CampaignWorkAssignmentListResponse = {
|
|
items: CampaignWorkAssignment[];
|
|
next_cursor?: string | null;
|
|
has_more: boolean;
|
|
};
|
|
|
|
export type CampaignWorkAssignmentEvent = {
|
|
id: string;
|
|
assignment_id: string;
|
|
event_kind: string;
|
|
actor_user_id?: string | null;
|
|
actor_label: string;
|
|
status: CampaignWorkAssignmentStatus;
|
|
assignee_type: CampaignWorkAssigneeType;
|
|
assignee_id: string;
|
|
assignee_label: string;
|
|
resolution_state: CampaignWorkAssignmentResolutionState;
|
|
details: Record<string, unknown>;
|
|
created_at: string;
|
|
};
|
|
|
|
export type CampaignWorkAssignmentHistoryResponse = {
|
|
items: CampaignWorkAssignmentEvent[];
|
|
next_cursor?: string | null;
|
|
has_more: boolean;
|
|
};
|
|
|
|
export type CampaignArchiveEncryptionPolicy = {
|
|
available: boolean;
|
|
allowed_password_encryption_methods: Array<"aes" | "zip_standard">;
|
|
allowed_password_delivery_channels: Array<"separate_mail" | "sms" | "letter" | "phone" | "in_person">;
|
|
policy_hash: string;
|
|
source_path: Array<{
|
|
scope_type: string;
|
|
scope_id?: string | null;
|
|
path: string;
|
|
label: string;
|
|
applied_fields: string[];
|
|
policy: Record<string, unknown>;
|
|
}>;
|
|
reason: string;
|
|
diagnostics: Array<Record<string, unknown>>;
|
|
legacy_label: string;
|
|
};
|
|
|
|
export type CampaignUpdatePayload = {
|
|
external_id?: string | null;
|
|
name?: string | null;
|
|
status?: string | null;
|
|
description?: string | null;
|
|
};
|
|
|
|
export type CampaignCreateMinimalPayload = {
|
|
external_id?: string;
|
|
name?: string;
|
|
description?: string | null;
|
|
current_flow?: string;
|
|
current_step?: string;
|
|
};
|
|
|
|
export type CampaignCreateResponse = {
|
|
campaign: CampaignListItem & {
|
|
current_version_id?: string | null;
|
|
};
|
|
version: CampaignVersionListItem;
|
|
};
|
|
|
|
export type CampaignVersionListItem = {
|
|
id: string;
|
|
campaign_id: string;
|
|
version_number: number;
|
|
edit_revision: number;
|
|
strong_etag: string;
|
|
schema_version?: string;
|
|
source_filename?: string | null;
|
|
source_base_path?: string | null;
|
|
workflow_state?: string;
|
|
current_flow?: string;
|
|
current_step?: string | null;
|
|
is_complete?: boolean;
|
|
editor_state?: Record<string, unknown>;
|
|
autosaved_at?: string | null;
|
|
published_at?: string | null;
|
|
locked_at?: string | null;
|
|
locked_by_user_id?: string | null;
|
|
user_lock_state?: "temporary" | "permanent" | null;
|
|
user_locked_at?: string | null;
|
|
user_locked_by_user_id?: string | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
validation_summary?: Record<string, unknown> | null;
|
|
build_summary?: Record<string, unknown> | null;
|
|
execution_snapshot_hash?: string | null;
|
|
execution_snapshot_at?: string | null;
|
|
delivery_mode?: "synchronous" | "worker_queue" | "database_queue" | null;
|
|
delivery_mode_selected_at?: string | null;
|
|
archived_at?: string | null;
|
|
archived_by_user_id?: string | null;
|
|
};
|
|
|
|
export type CampaignLifecycleAction = {
|
|
allowed: boolean;
|
|
reason?: string | null;
|
|
};
|
|
|
|
export type CampaignLifecyclePolicy = {
|
|
policy_id: string;
|
|
policy_version: string;
|
|
state_token: string;
|
|
actions: Record<string, CampaignLifecycleAction>;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignCopyOptions = {
|
|
name?: string;
|
|
external_id?: string;
|
|
include_recipients: boolean;
|
|
include_files: boolean;
|
|
include_shares: boolean;
|
|
include_policies: boolean;
|
|
include_mail_profile: boolean;
|
|
};
|
|
|
|
export type CampaignTransferScope =
|
|
| "metadata"
|
|
| "template_config"
|
|
| "recipients"
|
|
| "attachments"
|
|
| "review_state"
|
|
| "delivery_history";
|
|
|
|
export type CampaignPortablePackage = {
|
|
format: "govoplan.campaign-portable";
|
|
format_version: string;
|
|
package_id: string;
|
|
exported_at: string;
|
|
source: Record<string, unknown>;
|
|
scopes: CampaignTransferScope[];
|
|
manifest: Record<string, unknown>;
|
|
payload: Record<string, unknown>;
|
|
integrity: { algorithm: string; package_sha256: string };
|
|
};
|
|
|
|
export type CampaignTransferPlanItem = {
|
|
scope: CampaignTransferScope;
|
|
code: string;
|
|
summary: string;
|
|
item_count?: number | null;
|
|
};
|
|
|
|
export type CampaignImportPreview = {
|
|
compatible: boolean;
|
|
package_id?: string | null;
|
|
package_sha256?: string | null;
|
|
format_version?: string | null;
|
|
source: Record<string, unknown>;
|
|
available_scopes: CampaignTransferScope[];
|
|
selected_scopes: CampaignTransferScope[];
|
|
destination: { external_id?: string; name?: string; status?: string };
|
|
will_create: CampaignTransferPlanItem[];
|
|
will_skip: CampaignTransferPlanItem[];
|
|
warnings: string[];
|
|
errors: string[];
|
|
};
|
|
|
|
export type CampaignImportApplyResponse = CampaignCreateResponse & {
|
|
receipt: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignScheduleOccurrence = {
|
|
id: string;
|
|
schedule_id: string;
|
|
scheduled_for: string;
|
|
status: "prepared" | "accepted" | "uncertain" | "failed" | "skipped" | "superseded" | string;
|
|
idempotency_key?: string | null;
|
|
generated_campaign_id?: string | null;
|
|
generated_version_id?: string | null;
|
|
error?: string | null;
|
|
delivery_command_ids: string[];
|
|
recovery_state: string;
|
|
evidence: Record<string, unknown>;
|
|
last_checked_at?: string | null;
|
|
created_at: string;
|
|
};
|
|
|
|
export type CampaignSchedule = {
|
|
id: string;
|
|
campaign_id: string;
|
|
source_version_id: string;
|
|
name: string;
|
|
delivery_mode: "manual" | "autonomous";
|
|
recurrence_kind: "once" | "daily" | "weekly" | "monthly";
|
|
interval_count: number;
|
|
timezone: string;
|
|
starts_at: string;
|
|
next_fire_at?: string | null;
|
|
ends_at?: string | null;
|
|
max_occurrences: number;
|
|
occurrence_count: number;
|
|
active: boolean;
|
|
resource_revision: number;
|
|
last_fired_at?: string | null;
|
|
last_campaign_id?: string | null;
|
|
last_error?: string | null;
|
|
last_outcome?: string | null;
|
|
last_recovery_state?: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
occurrences: CampaignScheduleOccurrence[];
|
|
};
|
|
|
|
export type CampaignScheduleCreate = {
|
|
source_version_id: string;
|
|
name: string;
|
|
delivery_mode: CampaignSchedule["delivery_mode"];
|
|
recurrence_kind: CampaignSchedule["recurrence_kind"];
|
|
interval_count: number;
|
|
timezone: string;
|
|
starts_at: string;
|
|
ends_at?: string | null;
|
|
max_occurrences: number;
|
|
include_recipients: boolean;
|
|
include_files: boolean;
|
|
include_shares: boolean;
|
|
include_policies: boolean;
|
|
include_mail_profile: boolean;
|
|
};
|
|
|
|
export type CampaignVersionDetail = CampaignVersionListItem & {
|
|
review_build_token?: string | null;
|
|
raw_json: Record<string, unknown>;
|
|
campaign_json?: Record<string, unknown>;
|
|
mail_profile_migration_required?: boolean;
|
|
};
|
|
|
|
export type CampaignWorkspaceResponse = {
|
|
campaign: CampaignListItem | null;
|
|
versions: CampaignVersionListItem[];
|
|
current_version: CampaignVersionDetail | null;
|
|
summary: CampaignSummary | null;
|
|
selected_version_id?: string | null;
|
|
};
|
|
|
|
export type CampaignDeltaResponse = {
|
|
campaigns: CampaignListItem[];
|
|
deleted: DeltaDeletedItem[];
|
|
watermark?: string | null;
|
|
has_more: boolean;
|
|
full: boolean;
|
|
total: number;
|
|
page: number;
|
|
page_size: number;
|
|
pages: number;
|
|
};
|
|
|
|
export type CampaignWorkspaceDeltaResponse = CampaignWorkspaceResponse & {
|
|
deleted: DeltaDeletedItem[];
|
|
watermark?: string | null;
|
|
has_more: boolean;
|
|
full: boolean;
|
|
};
|
|
|
|
export type CampaignWorkspaceQuery = {
|
|
versionId?: string | null;
|
|
includeCurrentVersion?: boolean;
|
|
includeSummary?: boolean;
|
|
includeVersions?: boolean;
|
|
since?: string | null;
|
|
limit?: number;
|
|
};
|
|
|
|
export type RecipientImportColumnKind = "ignore" | "id" | "active" | "name" | "from" | "to" | "cc" | "bcc" | "reply_to" | "field" | "new_field" | "attachment_pattern";
|
|
|
|
export type RecipientImportColumnMappingProfileItem = {
|
|
columnIndex: number;
|
|
kind: RecipientImportColumnKind;
|
|
fieldName?: string | null;
|
|
newFieldName?: string | null;
|
|
};
|
|
|
|
export type RecipientImportMappingProfile = {
|
|
id: string;
|
|
name: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
columnCount: number;
|
|
headers: string[];
|
|
normalizedHeaders: string[];
|
|
orderedHeaderFingerprint: string;
|
|
unorderedHeaderFingerprint: string;
|
|
delimiter: "," | ";" | "\t";
|
|
headerRows: number;
|
|
quoted: boolean;
|
|
valueSeparators: string;
|
|
mappings: RecipientImportColumnMappingProfileItem[];
|
|
};
|
|
|
|
export type RecipientImportMappingProfilePayload = Omit<RecipientImportMappingProfile, "id" | "createdAt" | "updatedAt">;
|
|
|
|
export type RecipientImportMappingProfileListResponse = {
|
|
profiles: RecipientImportMappingProfile[];
|
|
};
|
|
|
|
export type CampaignAddressLookupCandidate = {
|
|
contact_id: string;
|
|
address_book_id: string;
|
|
display_name: string;
|
|
email?: string | null;
|
|
email_label?: string | null;
|
|
organization?: string | null;
|
|
role_title?: string | null;
|
|
tags: string[];
|
|
source_kind: string;
|
|
source_ref?: string | null;
|
|
source_revision?: string | null;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignAddressLookupResponse = {
|
|
available: boolean;
|
|
candidates: CampaignAddressLookupCandidate[];
|
|
};
|
|
|
|
export type CampaignRecipientAddressSource = {
|
|
source_id: string;
|
|
source_label: string;
|
|
source_kind: string;
|
|
source_revision: string;
|
|
recipient_count: number;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignRecipientAddressSourcesResponse = {
|
|
available: boolean;
|
|
sources: CampaignRecipientAddressSource[];
|
|
};
|
|
|
|
export type CampaignDistributionListParameter = {
|
|
key: string;
|
|
value_type: "string" | "integer" | "number" | "boolean" | "date" | "datetime" | "string_list";
|
|
label?: string | null;
|
|
required: boolean;
|
|
default?: unknown;
|
|
allowed_values: unknown[];
|
|
minimum?: number | null;
|
|
maximum?: number | null;
|
|
pattern?: string | null;
|
|
description?: string | null;
|
|
};
|
|
|
|
export type CampaignDistributionListSource = {
|
|
id: string;
|
|
tenant_id: string;
|
|
name: string;
|
|
revision_id: string;
|
|
revision: number;
|
|
definition_hash: string;
|
|
definition_kind: string;
|
|
description?: string | null;
|
|
status: string;
|
|
entry_count: number;
|
|
read_only: boolean;
|
|
stale: boolean;
|
|
parameters: CampaignDistributionListParameter[];
|
|
updated_at?: string | null;
|
|
provenance: Record<string, unknown>;
|
|
metadata: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionListSourcesResponse = {
|
|
available: boolean;
|
|
expand_available: boolean;
|
|
sources: CampaignDistributionListSource[];
|
|
};
|
|
|
|
export type CampaignDistributionSourceReference = {
|
|
provider: string;
|
|
resource_type: string;
|
|
resource_id: string;
|
|
revision?: string | null;
|
|
fingerprint?: string | null;
|
|
label?: string | null;
|
|
metadata: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionExplanation = {
|
|
code: string;
|
|
message: string;
|
|
severity: "info" | "warning" | "error" | string;
|
|
provider?: string | null;
|
|
source?: CampaignDistributionSourceReference | null;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionChannelCandidate = {
|
|
channel: "email" | "postal" | "internal_mail" | "portal" | string;
|
|
target: string;
|
|
target_key: string;
|
|
status: string;
|
|
contact_point_id?: string | null;
|
|
locale?: string | null;
|
|
preferred: boolean;
|
|
reason_code?: string | null;
|
|
explanation?: string | null;
|
|
source?: CampaignDistributionSourceReference | null;
|
|
decision_provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionRecipient = {
|
|
recipient_key: string;
|
|
display_name: string;
|
|
status: string;
|
|
channels: CampaignDistributionChannelCandidate[];
|
|
identity_id?: string | null;
|
|
account_id?: string | null;
|
|
contact_id?: string | null;
|
|
organization_unit_id?: string | null;
|
|
function_id?: string | null;
|
|
source_entry_ids: string[];
|
|
explanations: CampaignDistributionExplanation[];
|
|
attributes: Record<string, unknown>;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionProviderEvidence = {
|
|
provider: string;
|
|
source: CampaignDistributionSourceReference;
|
|
actual_revision?: string | null;
|
|
actual_fingerprint?: string | null;
|
|
stale: boolean;
|
|
generated_at?: string | null;
|
|
details: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignDistributionListExpansion = {
|
|
source: CampaignDistributionListSource;
|
|
request: Record<string, unknown>;
|
|
recipients: CampaignDistributionRecipient[];
|
|
excluded: CampaignDistributionRecipient[];
|
|
diagnostics: CampaignDistributionExplanation[];
|
|
provider_evidence: CampaignDistributionProviderEvidence[];
|
|
expansion_hash: string;
|
|
generated_at?: string | null;
|
|
snapshot_id?: string | null;
|
|
stale: boolean;
|
|
truncated: boolean;
|
|
};
|
|
|
|
export type CampaignDistributionListExpansionInput = {
|
|
list_id: string;
|
|
revision?: number | null;
|
|
effective_at?: string | null;
|
|
purpose?: string;
|
|
requested_channels: Array<"email" | "postal" | "internal_mail" | "portal">;
|
|
parameters: Record<string, unknown>;
|
|
idempotency_key?: string | null;
|
|
};
|
|
|
|
export type CampaignPostboxDirectoryEntry = {
|
|
id: string;
|
|
address: string;
|
|
address_key: string;
|
|
name: string;
|
|
status: string;
|
|
classification: string;
|
|
organization_unit_id?: string | null;
|
|
organization_unit_name?: string | null;
|
|
function_id?: string | null;
|
|
function_name?: string | null;
|
|
context_key?: string | null;
|
|
holder_count: number;
|
|
vacant: boolean;
|
|
};
|
|
|
|
export type CampaignPostboxTemplate = {
|
|
id: string;
|
|
slug: string;
|
|
name: string;
|
|
description?: string | null;
|
|
published_revision_id: string;
|
|
function_type_id?: string | null;
|
|
scope_kind: string;
|
|
scope_id?: string | null;
|
|
classification: string;
|
|
allow_vacant_delivery: boolean;
|
|
};
|
|
|
|
export type CampaignPostboxFunction = {
|
|
id: string;
|
|
slug: string;
|
|
name: string;
|
|
function_type_id?: string | null;
|
|
};
|
|
|
|
export type CampaignPostboxOrganizationUnit = {
|
|
id: string;
|
|
slug: string;
|
|
name: string;
|
|
unit_type_id?: string | null;
|
|
parent_id?: string | null;
|
|
functions: CampaignPostboxFunction[];
|
|
};
|
|
|
|
export type CampaignPostboxCatalog = {
|
|
available: boolean;
|
|
postboxes: CampaignPostboxDirectoryEntry[];
|
|
templates: CampaignPostboxTemplate[];
|
|
organization_units: CampaignPostboxOrganizationUnit[];
|
|
};
|
|
|
|
export type CampaignCalendarCatalogEntry = {
|
|
id: string;
|
|
name: string;
|
|
color?: string | null;
|
|
timezone: string;
|
|
source_kind: string;
|
|
writable: boolean;
|
|
};
|
|
|
|
export type CampaignCalendarCatalog = {
|
|
available: boolean;
|
|
reason?: string | null;
|
|
calendars: CampaignCalendarCatalogEntry[];
|
|
};
|
|
|
|
export type CampaignPrintTemplateOutputProfile = {
|
|
id: string;
|
|
label: string;
|
|
output_format: "html" | "text";
|
|
media_type: string;
|
|
channel: string;
|
|
capabilities: string[];
|
|
page: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignPrintTemplate = {
|
|
id: string;
|
|
name: string;
|
|
slug: string;
|
|
template_type: string;
|
|
status: string;
|
|
current_revision: number;
|
|
current_revision_id: string;
|
|
published_revision_id?: string | null;
|
|
description?: string | null;
|
|
read_only: boolean;
|
|
revision?: {
|
|
revision: number;
|
|
output_profiles: CampaignPrintTemplateOutputProfile[];
|
|
required_fields: Array<{path: string;label?: string | null;required: boolean;}>;
|
|
} | null;
|
|
};
|
|
|
|
export type CampaignPrintTemplatesResponse = {
|
|
available: boolean;
|
|
templates: CampaignPrintTemplate[];
|
|
};
|
|
|
|
export type CampaignContentLibraryTarget = "subject" | "text" | "html";
|
|
|
|
export type CampaignContentLibraryItem = {
|
|
id: string;
|
|
name: string;
|
|
description?: string | null;
|
|
template_type: string;
|
|
kind: "fragment" | "campaign_part";
|
|
status: string;
|
|
scope_type: "tenant" | "group" | "user";
|
|
scope_id?: string | null;
|
|
read_only: boolean;
|
|
current_revision: number;
|
|
revision: number;
|
|
revision_id: string;
|
|
locale?: string | null;
|
|
published: boolean;
|
|
targets: CampaignContentLibraryTarget[];
|
|
subject?: string | null;
|
|
text?: string | null;
|
|
html?: string | null;
|
|
body_mode: "text" | "html" | "both";
|
|
required_fields: Array<{
|
|
path: string;
|
|
value_type: "string" | "integer" | "number" | "boolean" | "date" | "datetime" | "object" | "array";
|
|
label?: string | null;
|
|
required: boolean;
|
|
description?: string | null;
|
|
}>;
|
|
};
|
|
|
|
export type CampaignContentLibraryResponse = {
|
|
available: boolean;
|
|
writable: boolean;
|
|
reason?: string | null;
|
|
items: CampaignContentLibraryItem[];
|
|
};
|
|
|
|
export type CampaignContentLibrarySaveInput = {
|
|
name: string;
|
|
description?: string | null;
|
|
kind: "fragment" | "campaign_part";
|
|
target?: CampaignContentLibraryTarget | null;
|
|
subject?: string | null;
|
|
text?: string | null;
|
|
html?: string | null;
|
|
body_mode: "text" | "html" | "both";
|
|
locale: string;
|
|
visibility: "personal" | "tenant";
|
|
};
|
|
|
|
export type CampaignRecipientSnapshotItem = {
|
|
contact_id: string;
|
|
display_name: string;
|
|
email: string;
|
|
email_label?: string | null;
|
|
fields: Record<string, unknown>;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignRecipientSnapshotExcludedItem = {
|
|
contact_id: string;
|
|
display_name: string;
|
|
channel: string;
|
|
target: string;
|
|
contact_point_id?: string | null;
|
|
status: string;
|
|
reason_code?: string | null;
|
|
explanation?: string | null;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignRecipientAddressSourceSnapshot = {
|
|
source_id: string;
|
|
source_label: string;
|
|
source_kind: string;
|
|
source_revision: string;
|
|
generated_at: string;
|
|
recipients: CampaignRecipientSnapshotItem[];
|
|
excluded: CampaignRecipientSnapshotExcludedItem[];
|
|
included_count: number;
|
|
excluded_count: number;
|
|
purpose: string;
|
|
provenance: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignVersionUpdatePayload = {
|
|
campaign_json?: Record<string, unknown> | null;
|
|
current_flow?: string | null;
|
|
current_step?: string | null;
|
|
workflow_state?: string | null;
|
|
is_complete?: boolean | null;
|
|
editor_state?: Record<string, unknown> | null;
|
|
source_filename?: string | null;
|
|
source_base_path?: string | null;
|
|
migrate_legacy_mail_settings?: boolean;
|
|
base_revision?: number;
|
|
reconciliation_kind?: "none" | "auto_merge" | "manual";
|
|
resolved_conflict_paths?: string[];
|
|
};
|
|
|
|
export type CampaignPartialValidationPayload = {
|
|
campaign_json?: Record<string, unknown> | null;
|
|
section?: string | null;
|
|
};
|
|
|
|
export type CampaignPartialValidationResponse = {
|
|
ok: boolean;
|
|
section?: string | null;
|
|
error_count: number;
|
|
warning_count: number;
|
|
info_count: number;
|
|
issues: Record<string, unknown>[];
|
|
};
|
|
|
|
export type CampaignRetentionReport = {
|
|
policy_status: "configured" | "defaults" | "unavailable" | string;
|
|
policy_reason?: string | null;
|
|
effective_policy: {
|
|
store_raw_campaign_json?: boolean;
|
|
raw_campaign_json_retention_days?: number | null;
|
|
generated_eml_retention_days?: number | null;
|
|
stored_report_detail_retention_days?: number | null;
|
|
mock_mailbox_retention_days?: number | null;
|
|
audit_detail_retention_days?: number | null;
|
|
audit_detail_level?: string;
|
|
};
|
|
sources: Array<{
|
|
scope_type?: string | null;
|
|
path?: string | null;
|
|
label?: string | null;
|
|
applied_fields?: string[];
|
|
}>;
|
|
evidence: Record<string, {
|
|
state?: string;
|
|
redacted_at?: string | null;
|
|
retained_count?: number;
|
|
expired_count?: number;
|
|
not_generated_count?: number;
|
|
currently_readable_count?: number;
|
|
withdrawn_count?: number;
|
|
redacted_summary_count?: number;
|
|
summary_count?: number;
|
|
}>;
|
|
privacy_impact: {
|
|
state: string;
|
|
summary: string;
|
|
retained_categories: string[];
|
|
minimized_categories: string[];
|
|
};
|
|
};
|
|
|
|
export type CampaignSummary = {
|
|
generated_at?: string;
|
|
selected_version_id?: string | null;
|
|
campaign?: CampaignListItem;
|
|
current_version?: {
|
|
id: string;
|
|
version_number?: number;
|
|
schema_version?: string;
|
|
source_filename?: string | null;
|
|
created_at?: string | null;
|
|
validation_summary?: Record<string, unknown> | null;
|
|
build_summary?: Record<string, unknown> | null;
|
|
delivery_mode?: "synchronous" | "worker_queue" | "database_queue" | null;
|
|
delivery_mode_selected_at?: string | null;
|
|
} | null;
|
|
cards?: {
|
|
jobs_total?: number;
|
|
inactive?: number;
|
|
queueable?: number;
|
|
queueable_unattempted?: number;
|
|
retryable?: number;
|
|
cancellable?: number;
|
|
needs_attention?: number;
|
|
sent?: number;
|
|
smtp_accepted?: number;
|
|
postbox_accepted?: number;
|
|
print_accepted?: number;
|
|
failed?: number;
|
|
outcome_unknown?: number;
|
|
not_attempted?: number;
|
|
skipped?: number;
|
|
queued_or_active?: number;
|
|
cancelled?: number;
|
|
partially_completed?: boolean;
|
|
imap_appended?: number;
|
|
imap_failed?: number;
|
|
imap_skipped?: number;
|
|
};
|
|
status_counts?: Record<string, Record<string, number>>;
|
|
issues?: Record<string, unknown>;
|
|
attachments?: Record<string, unknown>;
|
|
attempts?: Record<string, unknown>;
|
|
postbox_receipts?: Record<string, unknown>;
|
|
retention?: CampaignRetentionReport;
|
|
delivery?: Record<string, unknown>;
|
|
recent_failures?: Record<string, unknown>[];
|
|
};
|
|
|
|
export type CampaignQueuePayload = {
|
|
version_id?: string | null;
|
|
include_warnings?: boolean;
|
|
enqueue_celery?: boolean;
|
|
dry_run?: boolean;
|
|
};
|
|
|
|
export type CampaignDeliveryOptions = {
|
|
campaign_id: string;
|
|
version_id: string;
|
|
worker_queue_available: boolean;
|
|
postbox_available: boolean;
|
|
approval_gate: {
|
|
configured?: boolean;
|
|
available?: boolean;
|
|
approved?: boolean;
|
|
state?: string;
|
|
explanation?: string | null;
|
|
request_id?: string;
|
|
request_revision?: number;
|
|
subject_digest?: string;
|
|
};
|
|
synchronous_send: {
|
|
allowed?: boolean;
|
|
reason?: string | null;
|
|
message?: string | null;
|
|
eligible_recipient_job_count?: number;
|
|
policy?: {
|
|
max_recipient_jobs?: number;
|
|
source?: string;
|
|
deployment_max_recipient_jobs?: number;
|
|
tenant_max_recipient_jobs?: number | null;
|
|
};
|
|
};
|
|
};
|
|
|
|
export type CampaignApprovalRequestPayload = {
|
|
title: string;
|
|
description?: string | null;
|
|
steps: Array<{
|
|
key: string;
|
|
label: string;
|
|
selectors: Array<{
|
|
kind: "account" | "group" | "role" | "function_assignment" | "any_account";
|
|
value: string;
|
|
}>;
|
|
required_approvals: number;
|
|
rejection_policy: "fail_fast" | "collect";
|
|
signature_required: boolean;
|
|
forbidden_evidence_roles: Array<"author" | "owner" | "validator" | "builder" | "reviewer">;
|
|
}>;
|
|
unique_actors_across_steps: boolean;
|
|
policy_refs: string[];
|
|
idempotency_key: string;
|
|
};
|
|
|
|
export type CampaignSendNowPayload = {
|
|
version_id?: string | null;
|
|
include_warnings?: boolean;
|
|
check_files?: boolean;
|
|
validate_before_send?: boolean;
|
|
build_before_send?: boolean;
|
|
dry_run?: boolean;
|
|
use_rate_limit?: boolean;
|
|
enqueue_imap_task?: boolean;
|
|
};
|
|
|
|
export type CampaignAppendSentPayload = {
|
|
version_id?: string;
|
|
dry_run?: boolean;
|
|
enqueue_celery?: boolean;
|
|
run_inline?: boolean;
|
|
};
|
|
|
|
|
|
export type CampaignAttachmentPreviewFile = {
|
|
id: string;
|
|
version_id?: string;
|
|
blob_id?: string;
|
|
display_path: string;
|
|
filename: string;
|
|
owner_type: string;
|
|
owner_id: string;
|
|
checksum_sha256?: string;
|
|
size_bytes?: number;
|
|
content_type?: string | null;
|
|
linked_to_campaign?: boolean;
|
|
share?: Record<string, unknown> | null;
|
|
};
|
|
|
|
export type CampaignAttachmentPreviewRule = {
|
|
source: "global" | "entry";
|
|
entry_index: number;
|
|
entry_id?: string | null;
|
|
index: number;
|
|
attachment_id?: string | null;
|
|
label?: string | null;
|
|
required: boolean;
|
|
pattern: string;
|
|
base_path_name?: string | null;
|
|
base_path?: string | null;
|
|
status: "ok" | "missing" | "ambiguous";
|
|
behavior?: string | null;
|
|
zip_included?: boolean;
|
|
zip_mode?: "inherit" | "include" | "exclude";
|
|
zip_archive_id?: string | null;
|
|
zip_filename?: string | null;
|
|
matches: CampaignAttachmentPreviewFile[];
|
|
match_count: number;
|
|
linked_match_count?: number;
|
|
unlinked_match_count?: number;
|
|
issues: Record<string, unknown>[];
|
|
};
|
|
|
|
export type CampaignAttachmentPreviewResponse = {
|
|
campaign_id: string;
|
|
version_id: string;
|
|
shared_file_count: number;
|
|
candidate_file_count?: number;
|
|
matched_file_count?: number;
|
|
linked_file_count?: number;
|
|
unlinked_file_count?: number;
|
|
rules: CampaignAttachmentPreviewRule[];
|
|
linkable_files?: CampaignAttachmentPreviewFile[];
|
|
unused_shared_files: CampaignAttachmentPreviewFile[];
|
|
};
|
|
|
|
export type CampaignAttachmentPreviewPayload = {
|
|
include_unmatched?: boolean;
|
|
include_unlinked_candidates?: boolean;
|
|
campaign_json?: Record<string, unknown>;
|
|
};
|
|
|
|
export type CampaignAttachmentLinkMatchesPayload = {
|
|
campaign_json?: Record<string, unknown> | null;
|
|
dry_run?: boolean;
|
|
};
|
|
|
|
export type CampaignAttachmentLinkMatchesResponse = {
|
|
campaign_id: string;
|
|
version_id: string;
|
|
matched_file_count: number;
|
|
already_linked_file_count: number;
|
|
linked_file_count: number;
|
|
dry_run?: boolean;
|
|
linked_files: CampaignAttachmentPreviewFile[];
|
|
linkable_files: CampaignAttachmentPreviewFile[];
|
|
};
|
|
|
|
export type CampaignMockSendPayload = {
|
|
use_reviewed_build?: boolean;
|
|
version_id?: string | null;
|
|
send?: boolean;
|
|
include_warnings?: boolean;
|
|
include_needs_review?: boolean;
|
|
append_sent?: boolean;
|
|
clear_mailbox?: boolean;
|
|
check_files?: boolean;
|
|
};
|
|
|
|
export type CampaignReviewStatePayload = {
|
|
merge_progress?: boolean;
|
|
build_token?: string | null;
|
|
base_revision?: number | null;
|
|
decision_category_key?: string | null;
|
|
inspection_complete: boolean;
|
|
reviewed_message_keys: string[];
|
|
issue_decisions: Array<{
|
|
job_id: string;
|
|
decision: "accept";
|
|
reason?: string | null;
|
|
}>;
|
|
};
|
|
|
|
export type CampaignSendJobPayload = {
|
|
kind: "test" | "single_send" | "single_resend";
|
|
idempotency_key: string;
|
|
reason?: string;
|
|
context?: Record<string, unknown>;
|
|
include_warnings?: boolean;
|
|
use_rate_limit?: boolean;
|
|
enqueue_imap_task?: boolean;
|
|
};
|
|
|
|
|
|
export type CampaignJobsQuery = Omit<CampaignJobsQueryParameters, "since" | "limit">;
|
|
|
|
export type CampaignJobsResponse = {
|
|
jobs: Record<string, unknown>[];
|
|
page: number;
|
|
page_size: number;
|
|
total: number;
|
|
total_unfiltered: number;
|
|
pages: number;
|
|
cursor?: string | null;
|
|
next_cursor?: string | null;
|
|
counts: Record<string, Record<string, number>>;
|
|
filtered_counts: Record<string, Record<string, number>>;
|
|
review: {
|
|
inspection_complete?: boolean;
|
|
blocking_count?: number;
|
|
required_count?: number;
|
|
reviewed_required_count?: number;
|
|
bulk_acceptable_count?: number;
|
|
};
|
|
};
|
|
|
|
export type CampaignJobsDeltaResponse = CampaignJobsResponse & {
|
|
deleted: DeltaDeletedItem[];
|
|
watermark?: string | null;
|
|
has_more: boolean;
|
|
full: boolean;
|
|
};
|
|
|
|
export type CampaignJobDetailResponse = {
|
|
job: Record<string, unknown>;
|
|
attempts: {
|
|
smtp?: Record<string, unknown>[];
|
|
imap?: Record<string, unknown>[];
|
|
postbox?: Record<string, unknown>[];
|
|
print?: Record<string, unknown>[];
|
|
};
|
|
};
|
|
|
|
export type CampaignReportEmailPayload = {
|
|
to: string[];
|
|
version_id?: string;
|
|
include_jobs?: boolean;
|
|
attach_jobs_csv?: boolean;
|
|
attach_report_json?: boolean;
|
|
dry_run?: boolean;
|
|
idempotency_key?: string;
|
|
};
|
|
|
|
export type AggregateReportCount = {
|
|
value: number | null;
|
|
suppressed: boolean;
|
|
};
|
|
|
|
export type AggregateReportCampaign = {
|
|
id: string;
|
|
name: string;
|
|
status: string;
|
|
};
|
|
|
|
export type AggregateReportCampaignListItem = AggregateReportCampaign & {
|
|
updated_at: string;
|
|
};
|
|
|
|
export type AggregateCampaignReport = {
|
|
generated_at: string;
|
|
campaign: AggregateReportCampaign;
|
|
version_number: number | null;
|
|
completion_state: "not_started" | "in_progress" | "completed" | "partially_completed" | "incomplete" | "outcome_unknown" | "suppressed";
|
|
population: {
|
|
denominator: AggregateReportCount;
|
|
denominator_definition: string;
|
|
inactive_source_entries: AggregateReportCount;
|
|
excluded_or_blocked_jobs: AggregateReportCount;
|
|
};
|
|
outcomes: {
|
|
smtp_accepted: AggregateReportCount;
|
|
postbox_accepted: AggregateReportCount;
|
|
print_accepted: AggregateReportCount;
|
|
delivered: AggregateReportCount;
|
|
partially_accepted: AggregateReportCount;
|
|
failed: AggregateReportCount;
|
|
outcome_unknown: AggregateReportCount;
|
|
queued_or_active: AggregateReportCount;
|
|
cancelled: AggregateReportCount;
|
|
excluded: AggregateReportCount;
|
|
not_attempted: AggregateReportCount;
|
|
};
|
|
time_range: {
|
|
first_activity_at: string | null;
|
|
last_activity_at: string | null;
|
|
suppressed: boolean;
|
|
};
|
|
privacy: {
|
|
small_cell_threshold: number;
|
|
suppression_applied: boolean;
|
|
rule: string;
|
|
};
|
|
};
|
|
|
|
export async function listCampaigns(settings: ApiSettings): Promise<CampaignListItem[]> {
|
|
const response = await apiFetch<CampaignListResponse>(settings, "/api/v1/campaigns");
|
|
|
|
if (Array.isArray(response)) {
|
|
return response;
|
|
}
|
|
|
|
return response.campaigns ?? response.items ?? response.results ?? [];
|
|
}
|
|
|
|
export async function listAggregateReportCampaigns(
|
|
settings: ApiSettings)
|
|
: Promise<AggregateReportCampaignListItem[]> {
|
|
const response = await apiFetch<{campaigns: AggregateReportCampaignListItem[]}>(settings, "/api/v1/campaigns/aggregate-reports");
|
|
return response.campaigns;
|
|
}
|
|
|
|
export async function listCampaignsDelta(
|
|
settings: ApiSettings,
|
|
options: {since?: string | null;limit?: number;} = {})
|
|
: Promise<CampaignDeltaResponse> {
|
|
const params = new URLSearchParams();
|
|
if (options.since) params.set("since", options.since);
|
|
if (options.limit) params.set("limit", String(options.limit));
|
|
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignDeltaResponse>(settings, `/api/v1/campaigns/delta${suffix}`);
|
|
}
|
|
|
|
export async function listRecipientImportMappingProfiles(settings: ApiSettings): Promise<RecipientImportMappingProfile[]> {
|
|
const response = await apiFetch<RecipientImportMappingProfileListResponse>(settings, "/api/v1/campaigns/recipient-import/mapping-profiles");
|
|
return response.profiles ?? [];
|
|
}
|
|
|
|
export async function createRecipientImportMappingProfile(
|
|
settings: ApiSettings,
|
|
payload: RecipientImportMappingProfilePayload)
|
|
: Promise<RecipientImportMappingProfile> {
|
|
return apiFetch<RecipientImportMappingProfile>(settings, "/api/v1/campaigns/recipient-import/mapping-profiles", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function updateRecipientImportMappingProfile(
|
|
settings: ApiSettings,
|
|
profileId: string,
|
|
payload: RecipientImportMappingProfilePayload)
|
|
: Promise<RecipientImportMappingProfile> {
|
|
return apiFetch<RecipientImportMappingProfile>(settings, `/api/v1/campaigns/recipient-import/mapping-profiles/${encodeURIComponent(profileId)}`, {
|
|
method: "PUT",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function deleteRecipientImportMappingProfile(settings: ApiSettings, profileId: string): Promise<void> {
|
|
await apiFetch<void>(settings, `/api/v1/campaigns/recipient-import/mapping-profiles/${encodeURIComponent(profileId)}`, { method: "DELETE" });
|
|
}
|
|
|
|
export async function lookupCampaignAddresses(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
query: string,
|
|
limit = 25)
|
|
: Promise<CampaignAddressLookupResponse> {
|
|
const params = new URLSearchParams({ query, limit: String(limit) });
|
|
return apiFetch<CampaignAddressLookupResponse>(settings, `/api/v1/campaigns/${campaignId}/address-lookup?${params.toString()}`);
|
|
}
|
|
|
|
export async function listCampaignRecipientAddressSources(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<CampaignRecipientAddressSourcesResponse> {
|
|
return apiFetch<CampaignRecipientAddressSourcesResponse>(settings, `/api/v1/campaigns/${campaignId}/recipient-address-sources`);
|
|
}
|
|
|
|
export async function listCampaignRecipientDistributionLists(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
query = "")
|
|
: Promise<CampaignDistributionListSourcesResponse> {
|
|
const params = new URLSearchParams();
|
|
params.set("limit", "250");
|
|
if (query.trim()) params.set("query", query.trim());
|
|
const suffix = params.size ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignDistributionListSourcesResponse>(settings, `/api/v1/campaigns/${campaignId}/recipient-distribution-lists${suffix}`);
|
|
}
|
|
|
|
export async function previewCampaignRecipientDistributionList(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignDistributionListExpansionInput)
|
|
: Promise<CampaignDistributionListExpansion> {
|
|
return apiFetch<CampaignDistributionListExpansion>(settings, `/api/v1/campaigns/${campaignId}/recipient-distribution-lists/preview`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function snapshotCampaignRecipientDistributionList(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignDistributionListExpansionInput)
|
|
: Promise<CampaignDistributionListExpansion> {
|
|
return apiFetch<CampaignDistributionListExpansion>(settings, `/api/v1/campaigns/${campaignId}/recipient-distribution-lists/snapshot`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function getCampaignPostboxCatalog(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<CampaignPostboxCatalog> {
|
|
return apiFetch<CampaignPostboxCatalog>(settings, `/api/v1/campaigns/${campaignId}/postbox-catalog`);
|
|
}
|
|
|
|
export async function getCampaignCalendarInvitationCatalog(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<CampaignCalendarCatalog> {
|
|
return apiFetch<CampaignCalendarCatalog>(settings, `/api/v1/campaigns/${campaignId}/calendar-invitation-catalog`);
|
|
}
|
|
|
|
export async function listCampaignPrintTemplates(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
query = "")
|
|
: Promise<CampaignPrintTemplatesResponse> {
|
|
const suffix = query.trim() ? `?query=${encodeURIComponent(query.trim())}` : "";
|
|
return apiFetch<CampaignPrintTemplatesResponse>(settings, `/api/v1/campaigns/${campaignId}/print-templates${suffix}`);
|
|
}
|
|
|
|
export async function listCampaignContentLibrary(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
query = "")
|
|
: Promise<CampaignContentLibraryResponse> {
|
|
const suffix = query.trim() ? `?query=${encodeURIComponent(query.trim())}` : "";
|
|
return apiFetch<CampaignContentLibraryResponse>(settings, `/api/v1/campaigns/${campaignId}/content-library${suffix}`);
|
|
}
|
|
|
|
export async function saveCampaignContentLibraryItem(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignContentLibrarySaveInput)
|
|
: Promise<{template: CampaignContentLibraryItem;}> {
|
|
return apiFetch<{template: CampaignContentLibraryItem;}>(settings, `/api/v1/campaigns/${campaignId}/content-library`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function snapshotCampaignRecipientAddressSource(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
sourceId: string)
|
|
: Promise<CampaignRecipientAddressSourceSnapshot> {
|
|
return apiFetch<CampaignRecipientAddressSourceSnapshot>(settings, `/api/v1/campaigns/${campaignId}/recipient-address-sources/snapshot`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ source_id: sourceId, purpose: "campaign_delivery" })
|
|
});
|
|
}
|
|
|
|
export async function getCampaign(settings: ApiSettings, campaignId: string): Promise<CampaignListItem> {
|
|
return apiFetch<CampaignListItem>(settings, `/api/v1/campaigns/${campaignId}`);
|
|
}
|
|
|
|
export async function getCampaignArchiveEncryptionPolicy(
|
|
settings: ApiSettings,
|
|
campaignId: string
|
|
): Promise<CampaignArchiveEncryptionPolicy> {
|
|
return apiFetch<CampaignArchiveEncryptionPolicy>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/archive-encryption-policy`
|
|
);
|
|
}
|
|
|
|
export async function updateCampaignMetadata(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignUpdatePayload)
|
|
: Promise<CampaignListItem> {
|
|
return apiFetch<CampaignListItem>(settings, `/api/v1/campaigns/${campaignId}`, {
|
|
method: "PUT",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function archiveCampaign(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
expectedStateToken: string)
|
|
: Promise<CampaignListItem> {
|
|
return apiFetch<CampaignListItem>(settings, `/api/v1/campaigns/${campaignId}/archive`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ expected_state_token: expectedStateToken })
|
|
});
|
|
}
|
|
|
|
export async function getCampaignLifecyclePolicy(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId?: string | null)
|
|
: Promise<CampaignLifecyclePolicy> {
|
|
const suffix = versionId ? `?version_id=${encodeURIComponent(versionId)}` : "";
|
|
return apiFetch<CampaignLifecyclePolicy>(settings, `/api/v1/campaigns/${campaignId}/lifecycle-policy${suffix}`);
|
|
}
|
|
|
|
export async function deleteCampaign(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
expectedStateToken: string)
|
|
: Promise<void> {
|
|
await apiFetch<void>(settings, `/api/v1/campaigns/${campaignId}`, {
|
|
method: "DELETE",
|
|
body: JSON.stringify({ expected_state_token: expectedStateToken })
|
|
});
|
|
}
|
|
|
|
export async function copyCampaign(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
sourceVersionId: string,
|
|
expectedStateToken: string,
|
|
options: CampaignCopyOptions)
|
|
: Promise<CampaignCreateResponse> {
|
|
return apiFetch<CampaignCreateResponse>(settings, `/api/v1/campaigns/${campaignId}/copies`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
source_version_id: sourceVersionId,
|
|
expected_state_token: expectedStateToken,
|
|
...options,
|
|
name: options.name?.trim() || undefined,
|
|
external_id: options.external_id?.trim() || undefined
|
|
})
|
|
});
|
|
}
|
|
|
|
export async function exportCampaignPackage(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
scopes: CampaignTransferScope[])
|
|
: Promise<CampaignPortablePackage> {
|
|
return apiFetch<CampaignPortablePackage>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/exports`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ scopes })
|
|
});
|
|
}
|
|
|
|
export async function previewCampaignImport(
|
|
settings: ApiSettings,
|
|
payload: {
|
|
package: Record<string, unknown>;
|
|
selected_scopes?: CampaignTransferScope[] | null;
|
|
external_id?: string;
|
|
name?: string;
|
|
})
|
|
: Promise<CampaignImportPreview> {
|
|
return apiFetch<CampaignImportPreview>(settings, "/api/v1/campaign-transfers/imports/preview", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function importCampaignPackage(
|
|
settings: ApiSettings,
|
|
payload: {
|
|
package: Record<string, unknown>;
|
|
selected_scopes: CampaignTransferScope[];
|
|
external_id?: string;
|
|
name?: string;
|
|
expected_package_sha256: string;
|
|
})
|
|
: Promise<CampaignImportApplyResponse> {
|
|
return apiFetch<CampaignImportApplyResponse>(settings, "/api/v1/campaign-transfers/imports", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function listCampaignSchedules(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<CampaignSchedule[]> {
|
|
const response = await apiFetch<{items: CampaignSchedule[]}>(settings, `/api/v1/campaigns/${campaignId}/schedules`);
|
|
return response.items;
|
|
}
|
|
|
|
export async function createCampaignSchedule(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignScheduleCreate)
|
|
: Promise<CampaignSchedule> {
|
|
return apiFetch<CampaignSchedule>(settings, `/api/v1/campaigns/${campaignId}/schedules`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function setCampaignScheduleState(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
scheduleId: string,
|
|
active: boolean,
|
|
baseRevision: number)
|
|
: Promise<CampaignSchedule> {
|
|
return apiFetch<CampaignSchedule>(settings, `/api/v1/campaigns/${campaignId}/schedules/${scheduleId}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify({ active, base_revision: baseRevision })
|
|
});
|
|
}
|
|
|
|
export async function archiveCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
expectedStateToken: string)
|
|
: Promise<CampaignVersionListItem> {
|
|
return apiFetch<CampaignVersionListItem>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/archive`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ expected_state_token: expectedStateToken })
|
|
});
|
|
}
|
|
|
|
export async function createNewCampaign(
|
|
settings: ApiSettings,
|
|
overrides: CampaignCreateMinimalPayload = {})
|
|
: Promise<CampaignCreateResponse> {
|
|
const now = new Date();
|
|
const stamp = now.toISOString().slice(0, 19).replace(/[-:T]/g, "");
|
|
const payload = {
|
|
external_id: overrides.external_id ?? `new-campaign-${stamp}`,
|
|
name: overrides.name ?? "i18n:govoplan-campaign.new_campaign.1f0d021c",
|
|
description: overrides.description ?? "",
|
|
current_flow: overrides.current_flow ?? "create",
|
|
current_step: overrides.current_step ?? "basics"
|
|
};
|
|
|
|
return apiFetch<CampaignCreateResponse>(settings, "/api/v1/campaigns/new", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function getCampaignSchema(settings: ApiSettings): Promise<unknown> {
|
|
return apiFetch(settings, "/api/v1/schemas/campaign");
|
|
}
|
|
|
|
export async function getCampaignSchemaUi(settings: ApiSettings): Promise<unknown> {
|
|
return apiFetch(settings, "/api/v1/schemas/campaign/ui");
|
|
}
|
|
|
|
export async function getCampaignWorkspace(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: CampaignWorkspaceQuery = {})
|
|
: Promise<CampaignWorkspaceResponse> {
|
|
const params = new URLSearchParams();
|
|
if (options.versionId) params.set("version_id", options.versionId);
|
|
if (options.includeCurrentVersion !== undefined) params.set("include_current_version", String(options.includeCurrentVersion));
|
|
if (options.includeSummary !== undefined) params.set("include_summary", String(options.includeSummary));
|
|
if (options.includeVersions !== undefined) params.set("include_versions", String(options.includeVersions));
|
|
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignWorkspaceResponse>(settings, `/api/v1/campaigns/${campaignId}/workspace${suffix}`);
|
|
}
|
|
|
|
export async function getCampaignWorkspaceDelta(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: CampaignWorkspaceQuery = {},
|
|
requestOptions?: Pick<RequestInit, "cache" | "signal">)
|
|
: Promise<CampaignWorkspaceDeltaResponse> {
|
|
const params = new URLSearchParams();
|
|
if (options.versionId) params.set("version_id", options.versionId);
|
|
if (options.includeCurrentVersion !== undefined) params.set("include_current_version", String(options.includeCurrentVersion));
|
|
if (options.includeSummary !== undefined) params.set("include_summary", String(options.includeSummary));
|
|
if (options.includeVersions !== undefined) params.set("include_versions", String(options.includeVersions));
|
|
if (options.since) params.set("since", options.since);
|
|
if (options.limit) params.set("limit", String(options.limit));
|
|
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignWorkspaceDeltaResponse>(settings, `/api/v1/campaigns/${campaignId}/workspace/delta${suffix}`, requestOptions);
|
|
}
|
|
|
|
export async function listCampaignVersions(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<CampaignVersionListItem[]> {
|
|
return apiFetch<CampaignVersionListItem[]>(settings, `/api/v1/campaigns/${campaignId}/versions`);
|
|
}
|
|
|
|
export async function getCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
// Conflict reconciliation and discard/reload require the current revision,
|
|
// never an older coalesced or short-lived cached read.
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}`, { cache: "no-store" });
|
|
}
|
|
|
|
export async function unlockCampaignVersionValidation(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/unlock-validation`, {
|
|
method: "POST"
|
|
});
|
|
}
|
|
|
|
export async function lockCampaignVersionTemporarily(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/lock-temporarily`, {
|
|
method: "POST"
|
|
});
|
|
}
|
|
|
|
export async function unlockCampaignVersionUserLock(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/unlock-user-lock`, {
|
|
method: "POST"
|
|
});
|
|
}
|
|
|
|
export async function lockCampaignVersionPermanently(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/lock-permanently`, {
|
|
method: "POST"
|
|
});
|
|
}
|
|
|
|
export async function updateCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignVersionUpdatePayload,
|
|
ifMatch: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}`, {
|
|
method: "PUT",
|
|
headers: { "If-Match": ifMatch },
|
|
body: JSON.stringify(campaignVersionUpdateForRequest(payload))
|
|
});
|
|
}
|
|
|
|
export async function forkCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignVersionUpdatePayload = {})
|
|
: Promise<CampaignCreateResponse> {
|
|
return apiFetch<CampaignCreateResponse>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/fork`, {
|
|
method: "POST",
|
|
body: JSON.stringify(campaignVersionUpdateForRequest(payload))
|
|
});
|
|
}
|
|
|
|
export async function autosaveCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignVersionUpdatePayload,
|
|
ifMatch: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/autosave`, {
|
|
method: "POST",
|
|
headers: { "If-Match": ifMatch },
|
|
body: JSON.stringify(campaignVersionUpdateForRequest(payload))
|
|
});
|
|
}
|
|
|
|
export async function setCampaignVersionStep(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
currentStep: string,
|
|
currentFlow?: string | null)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/set-step`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ current_flow: currentFlow, current_step: currentStep })
|
|
});
|
|
}
|
|
|
|
export async function validatePartial(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignPartialValidationPayload = {})
|
|
: Promise<CampaignPartialValidationResponse> {
|
|
return apiFetch<CampaignPartialValidationResponse>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/validate-partial`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function publishCampaignVersion(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/publish`, {
|
|
method: "POST"
|
|
});
|
|
}
|
|
|
|
export async function validateVersion(
|
|
settings: ApiSettings,
|
|
versionId: string,
|
|
checkFiles = false,
|
|
linkUnsharedMatches = false)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/versions/${versionId}/validate`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ check_files: checkFiles, link_unshared_matches: linkUnsharedMatches })
|
|
});
|
|
}
|
|
|
|
export async function buildVersion(
|
|
settings: ApiSettings,
|
|
versionId: string,
|
|
writeEml = true)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/versions/${versionId}/build`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ write_eml: writeEml, idempotency_key: crypto.randomUUID() })
|
|
});
|
|
}
|
|
|
|
|
|
export function previewCampaignAttachments(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignAttachmentPreviewPayload = {})
|
|
: Promise<CampaignAttachmentPreviewResponse> {
|
|
return apiFetch<CampaignAttachmentPreviewResponse>(
|
|
settings,
|
|
`/api/v1/campaigns/${campaignId}/versions/${versionId}/attachments/preview`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export function linkCampaignAttachmentMatches(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignAttachmentLinkMatchesPayload = {})
|
|
: Promise<CampaignAttachmentLinkMatchesResponse> {
|
|
return apiFetch<CampaignAttachmentLinkMatchesResponse>(
|
|
settings,
|
|
`/api/v1/campaigns/${campaignId}/versions/${versionId}/attachments/link-matches`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export async function getCampaignSummary(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId?: string)
|
|
: Promise<CampaignSummary> {
|
|
const suffix = versionId ? `?version_id=${encodeURIComponent(versionId)}` : "";
|
|
return apiFetch<CampaignSummary>(settings, `/api/v1/campaigns/${campaignId}/summary${suffix}`);
|
|
}
|
|
|
|
export type CampaignDeliveryProgress = {
|
|
delivery_mode?: string | null;
|
|
workflow_state?: string;
|
|
campaign_id: string;
|
|
version_id: string;
|
|
generated_at: string;
|
|
total_jobs: number;
|
|
smtp: { total: number; processed: number; accepted: number; active: number; pending: number; failed: number; outcome_unknown: number; excluded: number; paused: number; cancelled: number };
|
|
imap: { total: number; processed: number; appended: number; active: number; pending: number; failed: number; outcome_unknown: number; excluded: number };
|
|
status_counts: { send: Record<string, number>; queue: Record<string, number>; imap: Record<string, number> };
|
|
};
|
|
|
|
export async function getCampaignDeliveryProgress(
|
|
settings: ApiSettings, campaignId: string, versionId: string, signal?: AbortSignal
|
|
): Promise<CampaignDeliveryProgress> {
|
|
return apiFetch<CampaignDeliveryProgress>(settings,
|
|
`/api/v1/campaigns/${campaignId}/delivery-progress?version_id=${encodeURIComponent(versionId)}`,
|
|
{ cache: "no-store", signal });
|
|
}
|
|
|
|
export async function getCampaignJobs(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: CampaignJobsQuery = {},
|
|
init?: Pick<RequestInit, "cache" | "signal">)
|
|
: Promise<CampaignJobsResponse> {
|
|
const params = campaignJobsQueryParams(options);
|
|
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignJobsResponse>(settings, `/api/v1/campaigns/${campaignId}/jobs${suffix}`, init);
|
|
}
|
|
|
|
export async function getCampaignJobsDelta(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: CampaignJobsQuery & {since?: string | null;limit?: number;} = {},
|
|
init?: Pick<RequestInit, "cache" | "signal">)
|
|
: Promise<CampaignJobsDeltaResponse> {
|
|
const params = campaignJobsQueryParams(options);
|
|
const suffix = params.size > 0 ? `?${params.toString()}` : "";
|
|
return apiFetch<CampaignJobsDeltaResponse>(settings, `/api/v1/campaigns/${campaignId}/jobs/delta${suffix}`, init);
|
|
}
|
|
|
|
export async function getCampaignJobDetail(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
jobId: string)
|
|
: Promise<CampaignJobDetailResponse> {
|
|
return apiFetch<CampaignJobDetailResponse>(settings, `/api/v1/campaigns/${campaignId}/jobs/${jobId}`);
|
|
}
|
|
|
|
export async function getCampaignReport(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId?: string)
|
|
: Promise<CampaignSummary> {
|
|
const params = new URLSearchParams({ include_jobs: "false" });
|
|
if (versionId) params.set("version_id", versionId);
|
|
return apiFetch<CampaignSummary>(settings, `/api/v1/campaigns/${campaignId}/report?${params.toString()}`);
|
|
}
|
|
|
|
export async function getAggregateCampaignReport(
|
|
settings: ApiSettings,
|
|
campaignId: string)
|
|
: Promise<AggregateCampaignReport> {
|
|
return apiFetch<AggregateCampaignReport>(
|
|
settings,
|
|
`/api/v1/campaigns/aggregate-reports/${encodeURIComponent(campaignId)}`
|
|
);
|
|
}
|
|
|
|
export async function downloadCampaignJobsCsv(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId?: string)
|
|
: Promise<void> {
|
|
const suffix = versionId ? `?version_id=${encodeURIComponent(versionId)}` : "";
|
|
await apiDownload(
|
|
settings,
|
|
`/api/v1/campaigns/${campaignId}/report/jobs.csv${suffix}`,
|
|
`campaign-${campaignId}${versionId ? `-${versionId}` : ""}-jobs.csv`
|
|
);
|
|
}
|
|
|
|
export async function downloadCampaignPrintArtifact(
|
|
settings: ApiSettings,
|
|
downloadPath: string,
|
|
filename: string)
|
|
: Promise<void> {
|
|
if (![
|
|
"/api/v1/campaigns/",
|
|
"/api/v1/files/"
|
|
].some((prefix) => downloadPath.startsWith(prefix))) {
|
|
throw new Error("The printable output download path is invalid.");
|
|
}
|
|
await apiDownload(settings, downloadPath, filename || "campaign-print-output.html");
|
|
}
|
|
|
|
export async function emailCampaignReport(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignReportEmailPayload)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/report/email`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function retryCampaignJobs(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: Record<string, unknown> = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/jobs/retry`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function sendUnattemptedCampaignJobs(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: Record<string, unknown> = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/jobs/send-unattempted`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function sendCampaignJob(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
jobId: string,
|
|
payload: CampaignSendJobPayload)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/jobs/${jobId}/send`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function resolveCampaignJobOutcome(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
jobId: string,
|
|
decision: "smtp_accepted" | "not_sent" | "imap_appended" | "imap_not_appended" | "postbox_accepted" | "postbox_not_accepted",
|
|
note?: string,
|
|
attemptId?: string)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/jobs/${jobId}/resolve-outcome`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ decision, note: note || null, attempt_id: attemptId || null })
|
|
});
|
|
}
|
|
|
|
export async function updateCampaignReviewState(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignReviewStatePayload)
|
|
: Promise<CampaignVersionDetail> {
|
|
return apiFetch<CampaignVersionDetail>(settings, `/api/v1/campaigns/${campaignId}/versions/${versionId}/review-state`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function queueCampaign(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignQueuePayload = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/queue`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function getCampaignDeliveryOptions(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId?: string | null)
|
|
: Promise<CampaignDeliveryOptions> {
|
|
const query = versionId ? `?version_id=${encodeURIComponent(versionId)}` : "";
|
|
return apiFetch<CampaignDeliveryOptions>(settings, `/api/v1/campaigns/${campaignId}/delivery-options${query}`);
|
|
}
|
|
|
|
export async function requestCampaignApproval(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
versionId: string,
|
|
payload: CampaignApprovalRequestPayload)
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(
|
|
settings,
|
|
`/api/v1/campaigns/${campaignId}/versions/${versionId}/approval-request`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export async function sendCampaignNow(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignSendNowPayload = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/send-now`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
|
|
export async function mockSendCampaign(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignMockSendPayload = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/mock-send`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export async function pauseCampaign(settings: ApiSettings, campaignId: string): Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/pause`, { method: "POST" });
|
|
}
|
|
|
|
export async function resumeCampaign(settings: ApiSettings, campaignId: string): Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/resume`, { method: "POST" });
|
|
}
|
|
|
|
export async function cancelCampaign(settings: ApiSettings, campaignId: string): Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/cancel`, { method: "POST" });
|
|
}
|
|
|
|
export async function appendSent(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignAppendSentPayload = {})
|
|
: Promise<Record<string, unknown>> {
|
|
return apiFetch<Record<string, unknown>>(settings, `/api/v1/campaigns/${campaignId}/append-sent`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
version_id: payload.version_id,
|
|
dry_run: payload.dry_run ?? false,
|
|
enqueue_celery: payload.enqueue_celery ?? true,
|
|
run_inline: payload.run_inline ?? false
|
|
})
|
|
});
|
|
}
|
|
|
|
export async function getCampaignShareTargets(settings: ApiSettings, campaignId: string): Promise<CampaignShareTargets> {
|
|
return apiFetch<CampaignShareTargets>(settings, `/api/v1/campaigns/${campaignId}/share-targets`);
|
|
}
|
|
|
|
export async function listCampaignCollaboration(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: {cursor?: string | null;limit?: number;} = {}
|
|
): Promise<CampaignCollaborationListResponse> {
|
|
const params = new URLSearchParams({ limit: String(options.limit ?? 25) });
|
|
if (options.cursor) params.set("cursor", options.cursor);
|
|
return apiFetch<CampaignCollaborationListResponse>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration?${params.toString()}`
|
|
);
|
|
}
|
|
|
|
export async function createCampaignCollaborationEntry(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: CampaignCollaborationCreate
|
|
): Promise<CampaignCollaborationEntry> {
|
|
return apiFetch<CampaignCollaborationEntry>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export async function withdrawCampaignCollaborationEntry(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
entryId: string
|
|
): Promise<CampaignCollaborationEntry> {
|
|
return apiFetch<CampaignCollaborationEntry>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/${encodeURIComponent(entryId)}/withdraw`,
|
|
{ method: "POST", body: JSON.stringify({}) }
|
|
);
|
|
}
|
|
|
|
export async function redactCampaignCollaborationEntry(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
entryId: string
|
|
): Promise<CampaignCollaborationEntry> {
|
|
return apiFetch<CampaignCollaborationEntry>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/${encodeURIComponent(entryId)}/redact`,
|
|
{ method: "POST", body: JSON.stringify({}) }
|
|
);
|
|
}
|
|
|
|
export function campaignCollaborationMentionProvider(
|
|
settings: ApiSettings,
|
|
campaignId: string
|
|
): ReferenceOptionProvider {
|
|
return apiReferenceOptionProvider(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/collaboration/mention-options`
|
|
);
|
|
}
|
|
|
|
export async function listCampaignWorkAssignments(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
options: { cursor?: string | null; limit?: number; statuses?: CampaignWorkAssignmentStatus[] } = {}
|
|
): Promise<CampaignWorkAssignmentListResponse> {
|
|
const params = new URLSearchParams({ limit: String(options.limit ?? 50) });
|
|
if (options.cursor) params.set("cursor", options.cursor);
|
|
for (const status of options.statuses ?? []) params.append("assignment_status", status);
|
|
return apiFetch<CampaignWorkAssignmentListResponse>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments?${params.toString()}`
|
|
);
|
|
}
|
|
|
|
export async function createCampaignWorkAssignment(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: {
|
|
purpose: string;
|
|
assignee: { type: CampaignWorkAssigneeType; id: string };
|
|
due_at?: string | null;
|
|
reference?: Pick<CampaignCollaborationReference, "kind" | "id"> | null;
|
|
mirror_to_tasks?: boolean;
|
|
}
|
|
): Promise<CampaignWorkAssignment> {
|
|
return apiFetch<CampaignWorkAssignment>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export async function reassignCampaignWorkAssignment(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
assignmentId: string,
|
|
payload: {
|
|
expected_revision: number;
|
|
assignee: { type: CampaignWorkAssigneeType; id: string };
|
|
reason?: string | null;
|
|
mirror_to_tasks?: boolean;
|
|
}
|
|
): Promise<CampaignWorkAssignment> {
|
|
return apiFetch<CampaignWorkAssignment>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments/${encodeURIComponent(assignmentId)}/reassign`,
|
|
{ method: "POST", body: JSON.stringify(payload) }
|
|
);
|
|
}
|
|
|
|
export async function transitionCampaignWorkAssignment(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
assignment: Pick<CampaignWorkAssignment, "id" | "resource_revision">,
|
|
action: "accept" | "start" | "complete" | "reject" | "cancel"
|
|
): Promise<CampaignWorkAssignment> {
|
|
return apiFetch<CampaignWorkAssignment>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments/${encodeURIComponent(assignment.id)}/transition`,
|
|
{ method: "POST", body: JSON.stringify({ expected_revision: assignment.resource_revision, action }) }
|
|
);
|
|
}
|
|
|
|
export async function listCampaignWorkAssignmentHistory(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
assignmentId: string,
|
|
cursor?: string | null
|
|
): Promise<CampaignWorkAssignmentHistoryResponse> {
|
|
const params = new URLSearchParams({ limit: "50" });
|
|
if (cursor) params.set("cursor", cursor);
|
|
return apiFetch<CampaignWorkAssignmentHistoryResponse>(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments/${encodeURIComponent(assignmentId)}/history?${params.toString()}`
|
|
);
|
|
}
|
|
|
|
export async function reconcileCampaignWorkAssignments(
|
|
settings: ApiSettings,
|
|
campaignId: string
|
|
): Promise<{ checked: number; changed: number; assignments: CampaignWorkAssignment[] }> {
|
|
return apiFetch(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments/reconcile`,
|
|
{ method: "POST" }
|
|
);
|
|
}
|
|
|
|
export function campaignWorkAssignmentTargetProvider(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
assigneeType: CampaignWorkAssigneeType
|
|
): ReferenceOptionProvider {
|
|
return apiReferenceOptionProvider(
|
|
settings,
|
|
`/api/v1/campaigns/${encodeURIComponent(campaignId)}/assignments/options`,
|
|
{ assignee_type: assigneeType }
|
|
);
|
|
}
|
|
|
|
export function campaignShareTargetProvider(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
targetType: "user" | "group"
|
|
): ReferenceOptionProvider {
|
|
return apiReferenceOptionProvider(
|
|
settings,
|
|
`/api/v1/campaigns/${campaignId}/share-target-options`,
|
|
{ target_type: targetType }
|
|
);
|
|
}
|
|
|
|
export async function getCampaignShares(settings: ApiSettings, campaignId: string): Promise<CampaignShare[]> {
|
|
const pageSize = 500;
|
|
const shares: CampaignShare[] = [];
|
|
for (let page = 1; ; page += 1) {
|
|
const response = await apiFetch<{shares: CampaignShare[];pages?: number;}>(settings, `/api/v1/campaigns/${campaignId}/shares?page=${page}&page_size=${pageSize}`);
|
|
shares.push(...response.shares);
|
|
if (page >= (response.pages ?? 1)) {
|
|
return shares;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function updateCampaignOwner(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: {owner_user_id?: string | null;owner_group_id?: string | null;})
|
|
: Promise<CampaignListItem> {
|
|
return apiFetch<CampaignListItem>(settings, `/api/v1/campaigns/${campaignId}/owner`, { method: "PUT", body: JSON.stringify(payload) });
|
|
}
|
|
|
|
export async function upsertCampaignShare(
|
|
settings: ApiSettings,
|
|
campaignId: string,
|
|
payload: {target_type: "user" | "group";target_id: string;permission: "read" | "write";})
|
|
: Promise<CampaignShare> {
|
|
return apiFetch<CampaignShare>(settings, `/api/v1/campaigns/${campaignId}/shares`, { method: "POST", body: JSON.stringify(payload) });
|
|
}
|
|
|
|
export async function revokeCampaignShare(settings: ApiSettings, campaignId: string, shareId: string): Promise<void> {
|
|
await apiFetch<void>(settings, `/api/v1/campaigns/${campaignId}/shares/${shareId}`, { method: "DELETE" });
|
|
}
|