diff --git a/README.md b/README.md index da6a9c7..deec163 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ From your backend: `norbix.hub.code.get_code_functions(integrationId=...)`, `get_code_function_qualifiers(...)`, `invoke_code_function(functionRef=..., payload=..., invocationType="Sync")`, `get_code_function_event_sample(source="database")` and `get_code_function_runs(triggerId=...)`. Details and the typed views -(`as_user_change`, `as_file_change`, `as_payment`, `as_scheduled_task`, `payload()`): +(`as_user_change`, `as_file_change`, `as_payment`, `as_payment_order`, `as_scheduled_task`, `payload()`): [docs/hub/code.md](./docs/hub/code.md). ## Errors diff --git a/docs/api/_index.md b/docs/api/_index.md index bc9a9b7..aea4a47 100644 --- a/docs/api/_index.md +++ b/docs/api/_index.md @@ -7,4 +7,5 @@ | [`echo`](./echo.md) | 1 | | [`files`](./files.md) | 10 | | [`membership`](./membership.md) | 18 | +| [`payments`](./payments.md) | 4 | | [`public`](./public.md) | 2 | diff --git a/docs/api/payments.md b/docs/api/payments.md new file mode 100644 index 0000000..fb828bd --- /dev/null +++ b/docs/api/payments.md @@ -0,0 +1,49 @@ +# API · Payments + +Access with `norbix.api.payments`. + +| Method | Verb | Path | Scope | +| --- | --- | --- | --- | +| `create_payment_order` | `POST` | `/{version}/payments/orders` | `project` | +| `get_payment_order` | `GET` | `/{version}/payments/orders/{Id}` | `project` | +| `get_payment_orders` | `GET` | `/{version}/payments/orders` | `project` | +| `start_payment_checkout` | `POST` | `/{version}/payments/orders/{Id}/checkout` | `project` | + +A payment order is what a buyer pays for: lines priced in minor units (cents), +a merchant reference and a price version. The order total is the sum of the +lines; Norbix computes it. + +## Taking a payment + +1. `create_payment_order` stores the order and gives back its id (`ord_…`). + Send an `idempotencyKey` (8 characters or more): the same body with the + same key gives back the same id, so a retry never makes a second order. +2. `start_payment_checkout` starts the provider checkout (Montonio, …) with a + payments integration of the project. Send the buyer to + `checkout["paymentUrl"]`. While a checkout is open, the call hands it back + with `reused` = `True`. +3. When the provider confirms the payment, the order becomes `Paid` and a + webhook destination or a Code function hears `payments.order.paid` (see + [webhooks-receiver.md](../webhooks-receiver.md) and + `FunctionEvent.as_payment_order()`). + +```python +created = client.api.payments.create_payment_order( + buyerUserId=user_id, + merchantReference="ad-1042-promo-1", + idempotencyKey="ad-1042-promo-1", + currency="EUR", + priceVersion="2026-10-01", + lines=[{"sku": "star-day", "title": "Star × day", "quantity": 21, "unitAmountMinor": 30}], + metadata={"adId": "ad_1042"}, +) +started = client.api.payments.start_payment_checkout( + created["id"], + integrationId=montonio_integration_id, + returnUrl="https://shop.example.com/orders/return", +) +redirect_to = started["checkout"]["paymentUrl"] + +order = client.api.payments.get_payment_order(created["id"])["item"] +paid = client.api.payments.get_payment_orders(buyerUserId=user_id, status="Paid")["list"]["items"] +``` diff --git a/docs/hub/code.md b/docs/hub/code.md index ee43bf3..da38eab 100644 --- a/docs/hub/code.md +++ b/docs/hub/code.md @@ -167,7 +167,8 @@ def handler(raw, _context): # AWS Lambda; Azure / Google p | `as_database_record_change()` | `collection`, `schema_id`, `schema_version`, `record_id`, `old`, `new`, `truncated`, `old_ref` / `new_ref` (over 200 KB the documents are left out and the refs say where to fetch them) | | `as_user_change()` | `user_id`, `old`, `new` | | `as_file_change()` | `old` (delete), `new` (upload), `path` | -| `as_payment()` | `integration_id`, `provider`, `provider_event_id`, `event_name`, `status`, `amount_minor`, `currency`, `external_ids`, `occurred_on`, `received_on` | +| `as_payment()` | `integration_id`, `provider`, `provider_event_id`, `event_name`, `order_id`, `status`, `amount_minor`, `currency`, `external_ids`, `occurred_on`, `received_on`; on `payments.order.*` it is the callback that changed the order | +| `as_payment_order()` | `payments.order.*` (`data.order`): `order_event_id` (the de-duplication key, the same on every retry), `event`, `from_`, `to`, `reason`, `order` (`id`, `status`, `lines`, `total_minor`, `settled_minor`, `refunded_minor`, `metadata`, `checkouts`, …), `payment` | | `as_scheduled_task()` | `task_id`, `name`, `fired_at` | | `as_ai_usage()` | `payload`, `target_user_id` | | `payload()` | the caller's JSON on a manual invoke, or a scheduler task's static payload; `None` when there is none | diff --git a/docs/webhooks-receiver.md b/docs/webhooks-receiver.md index 1029d81..7e2b5ce 100644 --- a/docs/webhooks-receiver.md +++ b/docs/webhooks-receiver.md @@ -70,6 +70,7 @@ flips give the **entity directly**; only an arbitrary mutation gives a | `database.records.inserted` | batch | `list` of documents | | `files.file.uploaded` | entity | `FileResourceRef` | | `payments.webhook.received` | entity | `PaymentFact` — the normalized payment fact (`event_name` = the provider's own name, `status`, `raw["amountMinor"]`, …); `event.metadata.payment` = provider ids | +| `payments.order.paid` / `partially_refunded` / `refunded` / `reversed` / `expired` | entity | `PaymentOrderEvent` — `order` (the order as stored after the change: `status`, `settled_minor`, `refunded_minor`, `metadata`, …), `payment` (the callback, a `PaymentFact`), `from_` / `to`; de-duplicate on `order_event_id` (the same on every retry). `event.metadata.order` = `{id, order_event_id, status}`, `event.metadata.payment` / `integration_id` from `data.payment` | Wrapper identifiers (entity id, schema, record ids) are lifted onto `event.metadata` (`event.metadata.user`, `.schema`, `.record`, `.records`). diff --git a/references/api2.dtos.ts b/references/api2.dtos.ts index 4d23ef6..3ec3c4c 100644 --- a/references/api2.dtos.ts +++ b/references/api2.dtos.ts @@ -1,5 +1,5 @@ /* Options: -Date: 2026-10-14 08:01:40 +Date: 2026-10-19 11:26:13 Version: 10.20 Tip: To override a DTO option, remove "//" prefix before updating BaseUrl: http://localhost:5002 @@ -44,6 +44,272 @@ export module CodeMashApi2 { } + export class JsonSchemaFieldDto + { + // @DataMember + public fieldName: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + + export class StringFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public format?: string; + + // @DataMember + public pattern?: string; + + // @DataMember + public minLength?: number; + + // @DataMember + public maxLength?: number; + + // @DataMember + public translateOptions?: IReadOnlyDictionary; + + // @DataMember + public default?: string; + + // @DataMember + public unique?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class DecimalFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public minimum?: number; + + // @DataMember + public maximum?: number; + + // @DataMember + public multipleOf?: number; + + // @DataMember + public default?: number; + + // @DataMember + public unique?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class CurrencyDefaultDto + { + // @DataMember + public value: number; + + // @DataMember + public currency: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + + export class CurrencyFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public allowedCurrencies?: IReadOnlyList; + + // @DataMember + public multipleOf?: number; + + // @DataMember + public minimum?: number; + + // @DataMember + public maximum?: number; + + // @DataMember + public default?: CurrencyDefaultDto; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class BooleanFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public default?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class DateFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public minimum?: number; + + // @DataMember + public maximum?: number; + + // @DataMember + public default?: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class IntegerFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public minimum?: number; + + // @DataMember + public maximum?: number; + + // @DataMember + public default?: number; + + // @DataMember + public unique?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class GeolocationFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public allowedTypes?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class TagsFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public minItems?: number; + + // @DataMember + public maxItems?: number; + + // @DataMember + public default?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class FileFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public storages?: IReadOnlyList; + + // @DataMember + public minItems?: number; + + // @DataMember + public maxItems?: number; + + // @DataMember + public allowedFileType?: string; + + // @DataMember + public maxSizeMb?: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class TaxonomySelectionFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public taxonomyId?: string; + + // @DataMember + public multiple: boolean; + + // @DataMember + public displayField?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class CollectionSelectionFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public collectionId?: string; + + // @DataMember + public displayField?: string; + + // @DataMember + public multiple: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class UserSelectionFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public multiple: boolean; + + // @DataMember + public displayField?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class RoleSelectionFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public multiple: boolean; + + // @DataMember + public displayField?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class EnumSelectionFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public values?: IReadOnlyList; + + // @DataMember + public multiple: boolean; + + // @DataMember + public default?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class ObjectFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public properties: IReadOnlyList; + + // @DataMember + public required?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class ArrayFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public items: JsonSchemaFieldDto; + + // @DataMember + public minItems?: number; + + // @DataMember + public maxItems?: number; + + // @DataMember + public uniqueItems?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class JsonFieldDto extends JsonSchemaFieldDto + { + // @DataMember + public maxBytes?: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + // @DataContract(Namespace="http://codemash.io/types/") export class RequestBase implements IVersionBasedRequest, IHasCorrelationIdRequest { @@ -181,6 +447,11 @@ export module CodeMashApi2 public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } + export interface IPublicRegistrationRequest + { + roles?: string[]; + } + export class CodeMashListPaginationRequestBase extends RequestBase implements IHasProjectId, IHasEnv { /** @description ID of your project. Can be passed in a header as norbix-project-id. */ @@ -233,6 +504,24 @@ export module CodeMashApi2 public constructor(init?: Partial) { (Object as any).assign(this, init); } } + // @DataContract + export class PaymentOrderLineInput + { + // @DataMember + public sku?: string; + + // @DataMember + public title?: string; + + // @DataMember + public quantity: number; + + // @DataMember + public unitAmountMinor: number; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + // @DataContract export enum CodeMashRelease { @@ -512,6 +801,7 @@ export module CodeMashApi2 { Registered = 0, PendingValidation = 2, + Invited = 4, Active = 8, Unregistered = 16, Suspended = 32, @@ -691,15 +981,10 @@ export module CodeMashApi2 // @DataMember public meta?: Object; - public constructor(init?: Partial) { (Object as any).assign(this, init); } - } - - export class JsonSchemaFieldDto - { // @DataMember - public fieldName: string; + public origin?: string; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } export class DataSchemaDto @@ -721,6 +1006,14 @@ export module CodeMashApi2 public constructor(init?: Partial) { (Object as any).assign(this, init); } } + export class SchemaUniqueIndexDto + { + // @DataMember + public fields: string[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + export class SchemaSettingsDto { // @DataMember @@ -732,6 +1025,9 @@ export module CodeMashApi2 // @DataMember public description?: string; + // @DataMember + public uniqueIndexes?: SchemaUniqueIndexDto[]; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -1067,6 +1363,136 @@ export module CodeMashApi2 public constructor(init?: Partial) { (Object as any).assign(this, init); } } + // @DataContract + export class PaymentOrderLineDto + { + // @DataMember + public sku: string; + + // @DataMember + public title: string; + + // @DataMember + public quantity: number; + + // @DataMember + public unitAmountMinor: number; + + // @DataMember + public amountMinor: number; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + + // @DataContract + export class PaymentOrderCheckoutDto + { + // @DataMember + public attempt: number; + + // @DataMember + public integrationId: string; + + // @DataMember + public provider: string; + + // @DataMember + public providerOrderId: string; + + // @DataMember + public providerReference: string; + + // @DataMember + public paymentUrl: string; + + // @DataMember + public method: string; + + // @DataMember + public startedOnUtc: string; + + // @DataMember + public expiresAtUtc: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + + // @DataContract + export class PaymentOrderDto + { + // @DataMember + public id: string; + + // @DataMember + public env: string; + + // @DataMember + public buyerUserId: string; + + // @DataMember + public merchantReference: string; + + // @DataMember + public currency: string; + + // @DataMember + public priceVersion: string; + + // @DataMember + public lines: PaymentOrderLineDto[] = []; + + // @DataMember + public totalMinor: number; + + // @DataMember + public metadata: { [index:string]: string; } = {}; + + // @DataMember + public status: string; + + // @DataMember + public createdOnUtc: string; + + // @DataMember + public updatedOnUtc: string; + + // @DataMember + public checkouts: PaymentOrderCheckoutDto[] = []; + + // @DataMember + public settledMinor?: number; + + // @DataMember + public refundedMinor: number; + + // @DataMember + public paidOnUtc?: string; + + // @DataMember + public providerPaymentId?: string; + + // @DataMember + public mismatches: string[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + + export class InAppNotificationDto + { + public id: string; + public projectId: string; + public userId: string; + public channel: string; + public eventName: string; + public payloadJson?: string; + public isRead: boolean; + public seenAtUtc?: string; + public readAtUtc?: string; + public createdAtUtc: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + } + // @DataContract export class ResponseError { @@ -1179,6 +1605,9 @@ export module CodeMashApi2 // @DataMember public status?: string; + // @DataMember + public warnings?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -1485,6 +1914,55 @@ export module CodeMashApi2 public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } + export class GetPaymentOrderResponse extends ResponseBase + { + public item?: PaymentOrderDto; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class GetPaymentOrdersResponse extends ResponseBase + { + public list?: PaginatedResponse; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class StartPaymentCheckoutResponse extends ResponseBase + { + public checkout?: PaymentOrderCheckoutDto; + public reused: boolean; + public order?: PaymentOrderDto; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class GetNotificationInboxResponse extends ResponseBase + { + public list?: PaginatedResponse; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class GetUnreadCountResponse extends ResponseBase + { + public count: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class MarkNotificationReadResponse extends ResponseBase + { + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + + export class MarkAllNotificationsReadResponse extends ResponseBase + { + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + } + // @DataContract export class AuthenticateResponse implements IHasSessionId, IHasBearerToken { @@ -1548,6 +2026,32 @@ export module CodeMashApi2 public constructor(init?: Partial) { (Object as any).assign(this, init); } } + export class SharedTypeGen + { + public typegen_StringFieldDto?: StringFieldDto; + public typegen_DecimalFieldDto?: DecimalFieldDto; + public typegen_CurrencyFieldDto?: CurrencyFieldDto; + public typegen_BooleanFieldDto?: BooleanFieldDto; + public typegen_DateFieldDto?: DateFieldDto; + public typegen_IntegerFieldDto?: IntegerFieldDto; + public typegen_GeolocationFieldDto?: GeolocationFieldDto; + public typegen_TagsFieldDto?: TagsFieldDto; + public typegen_FileFieldDto?: FileFieldDto; + public typegen_TaxonomySelectionFieldDto?: TaxonomySelectionFieldDto; + public typegen_CollectionSelectionFieldDto?: CollectionSelectionFieldDto; + public typegen_UserSelectionFieldDto?: UserSelectionFieldDto; + public typegen_RoleSelectionFieldDto?: RoleSelectionFieldDto; + public typegen_EnumSelectionFieldDto?: EnumSelectionFieldDto; + public typegen_ObjectFieldDto?: ObjectFieldDto; + public typegen_ArrayFieldDto?: ArrayFieldDto; + public typegen_JsonFieldDto?: JsonFieldDto; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + public getTypeName() { return 'SharedTypeGen'; } + public getMethod() { return 'POST'; } + public createResponse() {} + } + // @Route("/{version}/echo", "GET") export class Echo extends RequestBase implements IReturn { @@ -1889,11 +2393,28 @@ export module CodeMashApi2 public createResponse() { return new IdResponse(); } } + /** @description Membership */ + // @Route("/{version}/membership/auth/register/phone", "POST") + // @Api(Description="Membership") + // @DataContract + export class SavePhoneUser extends SaveUser implements IReturn + { + /** @description Phone number for the new user, in E.164 format. */ + // @DataMember + // @ApiMember(Description="Phone number for the new user, in E.164 format.", IsRequired=true) + public phone: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'SavePhoneUser'; } + public getMethod() { return 'POST'; } + public createResponse() { return new IdResponse(); } + } + /** @description Membership */ // @Route("/{version}/membership/auth/register/user-name", "POST") // @Api(Description="Membership") // @DataContract - export class SaveUserNameUser extends SaveUser implements IReturn + export class SaveUserNameUser extends SaveUser implements IReturn, IPublicRegistrationRequest { // @DataMember public password: string; @@ -1901,6 +2422,11 @@ export module CodeMashApi2 // @DataMember public userName: string; + /** @description Optional roles from the project's "Permitted user registration roles". Empty = the default registration role. */ + // @DataMember + // @ApiMember(Description="Optional roles from the project's \"Permitted user registration roles\". Empty = the default registration role.") + public roles?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } public getTypeName() { return 'SaveUserNameUser'; } public getMethod() { return 'POST'; } @@ -1911,7 +2437,7 @@ export module CodeMashApi2 // @Route("/{version}/membership/auth/register/email", "POST") // @Api(Description="Membership") // @DataContract - export class SaveEmailUser extends SaveUser implements IReturn + export class SaveEmailUser extends SaveUser implements IReturn, IPublicRegistrationRequest { // @DataMember public password: string; @@ -1919,25 +2445,13 @@ export module CodeMashApi2 // @DataMember public email: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } - public getTypeName() { return 'SaveEmailUser'; } - public getMethod() { return 'POST'; } - public createResponse() { return new IdResponse(); } - } - - /** @description Membership */ - // @Route("/{version}/membership/auth/register/phone", "POST") - // @Api(Description="Membership") - // @DataContract - export class SavePhoneUser extends SaveUser implements IReturn - { - /** @description Phone number for the new user, in E.164 format. */ + /** @description Optional roles from the project's "Permitted user registration roles". Empty = the default registration role. */ // @DataMember - // @ApiMember(Description="Phone number for the new user, in E.164 format.", IsRequired=true) - public phone: string; + // @ApiMember(Description="Optional roles from the project's \"Permitted user registration roles\". Empty = the default registration role.") + public roles?: string[]; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } - public getTypeName() { return 'SavePhoneUser'; } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'SaveEmailUser'; } public getMethod() { return 'POST'; } public createResponse() { return new IdResponse(); } } @@ -2078,6 +2592,31 @@ export module CodeMashApi2 // @ApiMember(Description="Filter to these specific user ids.") public userIds?: string[]; + /** @description Free text, case-insensitive: matches email, user name, display / first / last name or phone. */ + // @DataMember + // @ApiMember(Description="Free text, case-insensitive: matches email, user name, display / first / last name or phone.") + public search?: string; + + /** @description Case-insensitive part of the email. */ + // @DataMember + // @ApiMember(Description="Case-insensitive part of the email.") + public email?: string; + + /** @description Case-insensitive part of the user name. */ + // @DataMember + // @ApiMember(Description="Case-insensitive part of the user name.") + public userName?: string; + + /** @description Status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked. */ + // @DataMember + // @ApiMember(Description="Status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked.") + public statuses?: string[]; + + /** @description Login type names, any of: Service, Email, UserName, Phone, Guest, Social. */ + // @DataMember + // @ApiMember(Description="Login type names, any of: Service, Email, UserName, Phone, Guest, Social.") + public types?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } public getTypeName() { return 'GetUsersRequest'; } public getMethod() { return 'GET'; } @@ -2141,11 +2680,21 @@ export module CodeMashApi2 // @DataContract export class InviteUserRequest extends CodeMashRequestBase implements IReturn { - /** @description Email address the invitation is sent to. */ + /** @description Email address the invitation is sent to. It cannot be changed later. */ // @DataMember - // @ApiMember(Description="Email address the invitation is sent to.", IsRequired=true) + // @ApiMember(Description="Email address the invitation is sent to. It cannot be changed later.", IsRequired=true) public email: string; + /** @description The invited person's full name, e.g. "Rūta Petraitė". Stored as the full name, first name (first word) and last name (the rest). The user may change it when finishing. */ + // @DataMember + // @ApiMember(Description="The invited person's full name, e.g. \"Rūta Petraitė\". Stored as the full name, first name (first word) and last name (the rest). The user may change it when finishing.") + public fullName?: string; + + /** @description Optional. How e-mails greet the person ("Hi {salutation},"), e.g. "Rūta". Stored as the display name. When empty the full name is used. The user may change it when finishing. */ + // @DataMember + // @ApiMember(Description="Optional. How e-mails greet the person (\"Hi {salutation},\"), e.g. \"Rūta\". Stored as the display name. When empty the full name is used. The user may change it when finishing.") + public salutation?: string; + /** @description Database integration id. Optional — defaults to the request environment's default integration. */ // @DataMember // @ApiMember(Description="Database integration id. Optional — defaults to the request environment's default integration.") @@ -2157,6 +2706,53 @@ export module CodeMashApi2 public createResponse() { return new EmptyResponse(); } } + /** @description Membership */ + // @Route("/{version}/membership/auth/invitation/finish", "POST") + // @Api(Description="Membership") + // @DataContract + export class FinishInvitationRequest extends CodeMashRequestBase implements IReturn + { + /** @description One-time invitation token from the e-mail link (the #token= fragment). */ + // @DataMember + // @ApiMember(Description="One-time invitation token from the e-mail link (the #token= fragment).", IsRequired=true) + public token: string; + + /** @description The user's password. Validated against the project's complexity policy. */ + // @DataMember + // @ApiMember(Description="The user's password. Validated against the project's complexity policy.", IsRequired=true) + public password: string; + + /** @description Optional. The user's full name; replaces the one the admin entered (full name, first name = first word, last name = the rest). Empty = keep the admin's. */ + // @DataMember + // @ApiMember(Description="Optional. The user's full name; replaces the one the admin entered (full name, first name = first word, last name = the rest). Empty = keep the admin's.") + public fullName?: string; + + /** @description Optional. How e-mails greet the user (stored as the display name). Empty = keep the admin's, or the full name when the admin gave none. */ + // @DataMember + // @ApiMember(Description="Optional. How e-mails greet the user (stored as the display name). Empty = keep the admin's, or the full name when the admin gave none.") + public salutation?: string; + + /** @description Optional. Older form of Salutation (the display name); Salutation wins when both are sent. */ + // @DataMember + // @ApiMember(Description="Optional. Older form of Salutation (the display name); Salutation wins when both are sent.") + public displayName?: string; + + /** @description Optional first name; wins over the one taken from FullName. */ + // @DataMember + // @ApiMember(Description="Optional first name; wins over the one taken from FullName.") + public firstName?: string; + + /** @description Optional last name; wins over the one taken from FullName. */ + // @DataMember + // @ApiMember(Description="Optional last name; wins over the one taken from FullName.") + public lastName?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'FinishInvitationRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new EmptyResponse(); } + } + /** @description Membership */ // @Route("/{version}/membership/auth/{userId}/link-identity", "POST") // @Api(Description="Membership") @@ -2706,7 +3302,9 @@ export module CodeMashApi2 // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; + /** @description The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). */ // @DataMember + // @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) public taxonomyName: string; // @DataMember @@ -2752,7 +3350,9 @@ export module CodeMashApi2 // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; + /** @description The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). */ // @DataMember + // @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) public taxonomyName: string; // @DataMember @@ -2784,7 +3384,9 @@ export module CodeMashApi2 // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; + /** @description The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). */ // @DataMember + // @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) public taxonomyName: string; // @DataMember @@ -2816,7 +3418,9 @@ export module CodeMashApi2 // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; + /** @description The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). */ // @DataMember + // @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) public taxonomyName: string; // @DataMember @@ -3531,8 +4135,8 @@ export module CodeMashApi2 // @Api(Description="Registers or refreshes a push device for the signed-in user.") export class RegisterOwnPushDeviceRequest extends CodeMashRequestBase implements IReturn { - /** @description Who issued the token: expo (getExpoPushTokenAsync), fcm (Android / Firebase) or apns (iOS). */ - // @ApiMember(Description="Who issued the token: expo (getExpoPushTokenAsync), fcm (Android / Firebase) or apns (iOS).", IsRequired=true) + /** @description Who issued the token: fcm (Android / Firebase) or apns (iOS). The NATIVE device token — in an Expo app use getDevicePushTokenAsync(). Expo push tokens (provider 'expo') are refused. */ + // @ApiMember(Description="Who issued the token: fcm (Android / Firebase) or apns (iOS). The NATIVE device token — in an Expo app use getDevicePushTokenAsync(). Expo push tokens (provider 'expo') are refused.", IsRequired=true) public provider: string; /** @description The push token, exactly as the provider gave it. */ @@ -3667,6 +4271,161 @@ export module CodeMashApi2 public createResponse() { return new EmptyResponse(); } } + /** @description Stores a payment order with a fixed price for one of the project's users. Server only (service user API key). */ + // @Route("/{version}/payments/orders", "POST") + // @Api(Description="Stores a payment order with a fixed price for one of the project's users. Server only (service user API key).") + export class CreatePaymentOrderRequest extends CodeMashRequestBase implements IReturn + { + /** @description The user the order is for (usr_…). */ + // @ApiMember(Description="The user the order is for (usr_…).", IsRequired=true) + public buyerUserId: string; + + /** @description The project's own order reference, unique per project and environment (1–64 of A–Z a–z 0–9 . _ : -). */ + // @ApiMember(Description="The project's own order reference, unique per project and environment (1–64 of A–Z a–z 0–9 . _ : -).", IsRequired=true) + public merchantReference: string; + + /** @description 8–128 characters. Same key + same body = the stored order; same key + other body = 409. May be sent as the Idempotency-Key header instead. */ + // @ApiMember(Description="8–128 characters. Same key + same body = the stored order; same key + other body = 409. May be sent as the Idempotency-Key header instead.") + public idempotencyKey?: string; + + /** @description EUR. */ + // @ApiMember(Description="EUR.", IsRequired=true) + public currency: string; + + /** @description The version of the price list the server priced the lines with. */ + // @ApiMember(Description="The version of the price list the server priced the lines with.", IsRequired=true) + public priceVersion: string; + + /** @description 1–50 lines: sku, title, quantity, unitAmountMinor (cents). Norbix computes the amounts and the total. */ + // @ApiMember(Description="1–50 lines: sku, title, quantity, unitAmountMinor (cents). Norbix computes the amounts and the total.", IsRequired=true) + public lines: PaymentOrderLineInput[] = []; + + /** @description Up to 20 project values (e.g. adId). No personal or billing data. */ + // @ApiMember(Description="Up to 20 project values (e.g. adId). No personal or billing data.") + public metadata?: { [index:string]: string; }; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'CreatePaymentOrderRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new IdResponse(); } + } + + /** @description Reads one payment order. A buyer reads only their own orders. */ + // @Route("/{version}/payments/orders/{Id}", "GET") + // @Api(Description="Reads one payment order. A buyer reads only their own orders.") + export class GetPaymentOrderRequest extends CodeMashRequestBase implements IReturn + { + /** @description The order id (ord_…). */ + // @ApiMember(Description="The order id (ord_…).", IsRequired=true) + public id: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetPaymentOrderRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetPaymentOrderResponse(); } + } + + /** @description Lists payment orders, newest first. A buyer gets only their own orders. */ + // @Route("/{version}/payments/orders", "GET") + // @Api(Description="Lists payment orders, newest first. A buyer gets only their own orders.") + export class GetPaymentOrdersRequest extends CodeMashListPaginationRequestBase implements IReturn + { + /** @description Server only: one buyer's orders (usr_…). A buyer always gets their own. */ + // @ApiMember(Description="Server only: one buyer's orders (usr_…). A buyer always gets their own.") + public buyerUserId?: string; + + /** @description Only the order with this merchant reference. */ + // @ApiMember(Description="Only the order with this merchant reference.") + public merchantReference?: string; + + /** @description Only orders in this status (Created, CheckoutStarted, Paid, …). */ + // @ApiMember(Description="Only orders in this status (Created, CheckoutStarted, Paid, …).") + public status?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetPaymentOrdersRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetPaymentOrdersResponse(); } + } + + /** @description Opens a Montonio checkout for a stored order and answers where the buyer pays. The buyer (own order) or the server. */ + // @Route("/{version}/payments/orders/{Id}/checkout", "POST") + // @Api(Description="Opens a Montonio checkout for a stored order and answers where the buyer pays. The buyer (own order) or the server.") + export class StartPaymentCheckoutRequest extends CodeMashRequestBase implements IReturn + { + /** @description The order id (ord_…). */ + // @ApiMember(Description="The order id (ord_…).", IsRequired=true) + public id: string; + + /** @description The Montonio integration (int_…) of the project in the request's environment. */ + // @ApiMember(Description="The Montonio integration (int_…) of the project in the request's environment.", IsRequired=true) + public integrationId: string; + + /** @description bankLink (default), card, applePay or googlePay. */ + // @ApiMember(Description="bankLink (default), card, applePay or googlePay.") + public method?: string; + + /** @description Where the buyer comes back after paying; its origin must be one of the project's allowed origins. */ + // @ApiMember(Description="Where the buyer comes back after paying; its origin must be one of the project's allowed origins.", IsRequired=true) + public returnUrl: string; + + /** @description Bank links only: the country whose banks are shown first (default LT). */ + // @ApiMember(Description="Bank links only: the country whose banks are shown first (default LT).") + public preferredCountry?: string; + + /** @description Bank links only: one bank to open directly (the provider's bank code). */ + // @ApiMember(Description="Bank links only: one bank to open directly (the provider's bank code).") + public preferredProvider?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'StartPaymentCheckoutRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new StartPaymentCheckoutResponse(); } + } + + // @Route("/{version}/notifications/inbox", "GET") + export class GetNotificationInboxRequest extends CodeMashListPaginationRequestBase implements IReturn + { + public unreadOnly: boolean; + public channel?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetNotificationInboxRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetNotificationInboxResponse(); } + } + + // @Route("/{version}/notifications/inbox/unread-count", "GET") + export class GetUnreadCountRequest extends CodeMashRequestBase implements IReturn + { + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetUnreadCountRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetUnreadCountResponse(); } + } + + // @Route("/{version}/notifications/inbox/{notificationId}/read", "POST") + export class MarkNotificationReadRequest extends CodeMashRequestBase implements IReturn + { + public notificationId: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'MarkNotificationReadRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new MarkNotificationReadResponse(); } + } + + // @Route("/{version}/notifications/inbox/read-all", "POST") + export class MarkAllNotificationsReadRequest extends CodeMashRequestBase implements IReturn + { + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'MarkAllNotificationsReadRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new MarkAllNotificationsReadResponse(); } + } + /** @description Sign In */ // @Route("/auth", "GET,POST") // @Route("/auth/{provider}", "GET,POST") diff --git a/references/api_dtos.py b/references/api_dtos.py index 31fe756..7693132 100644 --- a/references/api_dtos.py +++ b/references/api_dtos.py @@ -1,5 +1,5 @@ """ Options: -Date: 2026-10-14 08:01:41 +Date: 2026-10-19 11:26:14 Version: 10.20 Tip: To override a DTO option, remove "#" prefix before updating BaseUrl: http://localhost:5002 @@ -27,6 +27,158 @@ Object = TypeVar('Object') +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class JsonSchemaFieldDto: + field_name: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class StringFieldDto(JsonSchemaFieldDto): + format: Optional[str] = None + pattern: Optional[str] = None + min_length: Optional[int] = None + max_length: Optional[int] = None + translate_options: Optional[IReadOnlyDictionary[str, str]] = None + default: Optional[str] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class DecimalFieldDto(JsonSchemaFieldDto): + minimum: Optional[Decimal] = None + maximum: Optional[Decimal] = None + multiple_of: Optional[Decimal] = None + default: Optional[Decimal] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CurrencyDefaultDto: + value: Decimal = decimal.Decimal(0) + currency: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CurrencyFieldDto(JsonSchemaFieldDto): + allowed_currencies: Optional[IReadOnlyList[str]] = None + multiple_of: Optional[Decimal] = None + minimum: Optional[Decimal] = None + maximum: Optional[Decimal] = None + default: Optional[CurrencyDefaultDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class BooleanFieldDto(JsonSchemaFieldDto): + default: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class DateFieldDto(JsonSchemaFieldDto): + minimum: Optional[int] = None + maximum: Optional[int] = None + default: Optional[int] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class IntegerFieldDto(JsonSchemaFieldDto): + minimum: Optional[int] = None + maximum: Optional[int] = None + default: Optional[int] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GeolocationFieldDto(JsonSchemaFieldDto): + allowed_types: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TagsFieldDto(JsonSchemaFieldDto): + min_items: Optional[int] = None + max_items: Optional[int] = None + default: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class FileFieldDto(JsonSchemaFieldDto): + storages: Optional[IReadOnlyList[str]] = None + min_items: Optional[int] = None + max_items: Optional[int] = None + allowed_file_type: Optional[str] = None + max_size_mb: Optional[Decimal] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TaxonomySelectionFieldDto(JsonSchemaFieldDto): + taxonomy_id: Optional[str] = None + multiple: bool = False + display_field: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CollectionSelectionFieldDto(JsonSchemaFieldDto): + collection_id: Optional[str] = None + display_field: Optional[str] = None + multiple: bool = False + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class UserSelectionFieldDto(JsonSchemaFieldDto): + multiple: bool = False + display_field: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class RoleSelectionFieldDto(JsonSchemaFieldDto): + multiple: bool = False + display_field: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class EnumSelectionFieldDto(JsonSchemaFieldDto): + values: Optional[IReadOnlyList[str]] = None + multiple: bool = False + default: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ObjectFieldDto(JsonSchemaFieldDto): + properties: Optional[IReadOnlyList[JsonSchemaFieldDto]] = None + required: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ArrayFieldDto(JsonSchemaFieldDto): + items: Optional[JsonSchemaFieldDto] = None + min_items: Optional[int] = None + max_items: Optional[int] = None + unique_items: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class JsonFieldDto(JsonSchemaFieldDto): + max_bytes: Optional[int] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class RequestBase(IVersionBasedRequest, IHasCorrelationIdRequest): @@ -165,6 +317,10 @@ class SaveUserWithRolesBase(SaveUser): roles: List[str] = field(default_factory=list) +class IPublicRegistrationRequest: + roles: Optional[List[str]] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class CodeMashListPaginationRequestBase(RequestBase, IHasProjectId, IHasEnv): @@ -223,6 +379,15 @@ class PagingArgs: ending_before: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderLineInput: + sku: Optional[str] = None + title: Optional[str] = None + quantity: int = 0 + unit_amount_minor: int = 0 + + class CodeMashRelease(str, Enum): NOT_SET = 'NotSet' COMMUNITY = 'Community' @@ -472,6 +637,7 @@ class LoginDto: class AuthStatus(IntEnum): REGISTERED = 0 PENDING_VALIDATION = 2 + INVITED = 4 ACTIVE = 8 UNREGISTERED = 16 SUSPENDED = 32 @@ -581,12 +747,7 @@ class TermDto: descriptions: Optional[Dict[str, str]] = None multi_parents: Optional[List[TermMultiParentDto]] = None meta: Optional[Object] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class JsonSchemaFieldDto: - field_name: Optional[str] = None + origin: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -602,12 +763,19 @@ class VisualSchemaDto: json: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class SchemaUniqueIndexDto: + fields: List[str] = field(default_factory=list) + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class SchemaSettingsDto: soft_delete: bool = False has_record_owner: bool = False description: Optional[str] = None + unique_indexes: Optional[List[SchemaUniqueIndexDto]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -776,6 +944,68 @@ class OwnPushMessageDto: read_at_utc: Optional[datetime.datetime] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderLineDto: + sku: Optional[str] = None + title: Optional[str] = None + quantity: int = 0 + unit_amount_minor: int = 0 + amount_minor: int = 0 + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderCheckoutDto: + attempt: int = 0 + integration_id: Optional[str] = None + provider: Optional[str] = None + provider_order_id: Optional[str] = None + provider_reference: Optional[str] = None + payment_url: Optional[str] = None + method: Optional[str] = None + started_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + expires_at_utc: datetime.datetime = datetime.datetime(1, 1, 1) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderDto: + id: Optional[str] = None + env: Optional[str] = None + buyer_user_id: Optional[str] = None + merchant_reference: Optional[str] = None + currency: Optional[str] = None + price_version: Optional[str] = None + lines: List[PaymentOrderLineDto] = field(default_factory=list) + total_minor: int = 0 + metadata: Dict[str, str] = field(default_factory=dict) + status: Optional[str] = None + created_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + updated_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + checkouts: List[PaymentOrderCheckoutDto] = field(default_factory=list) + settled_minor: Optional[int] = None + refunded_minor: int = 0 + paid_on_utc: Optional[datetime.datetime] = None + provider_payment_id: Optional[str] = None + mismatches: List[str] = field(default_factory=list) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class InAppNotificationDto: + id: Optional[str] = None + project_id: Optional[str] = None + user_id: Optional[str] = None + channel: Optional[str] = None + event_name: Optional[str] = None + payload_json: Optional[str] = None + is_read: bool = False + seen_at_utc: Optional[datetime.datetime] = None + read_at_utc: Optional[datetime.datetime] = None + created_at_utc: datetime.datetime = datetime.datetime(1, 1, 1) + + class IBindableContract: pass @@ -1091,6 +1321,72 @@ class GetOwnPushMessagesResponse(ResponseBase): list: Optional[PaginatedResponse[OwnPushMessageDto]] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetPaymentOrderResponse(ResponseBase): + item: Optional[PaymentOrderDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetPaymentOrdersResponse(ResponseBase): + list: Optional[PaginatedResponse[PaymentOrderDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class StartPaymentCheckoutResponse(ResponseBase): + checkout: Optional[PaymentOrderCheckoutDto] = None + reused: bool = False + order: Optional[PaymentOrderDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetNotificationInboxResponse(ResponseBase): + list: Optional[PaginatedResponse[InAppNotificationDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetUnreadCountResponse(ResponseBase): + count: int = 0 + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkNotificationReadResponse(ResponseBase): + pass + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkAllNotificationsReadResponse(ResponseBase): + pass + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class SharedTypeGen: + typegen__string_field_dto: Optional[StringFieldDto] = None + typegen__decimal_field_dto: Optional[DecimalFieldDto] = None + typegen__currency_field_dto: Optional[CurrencyFieldDto] = None + typegen__boolean_field_dto: Optional[BooleanFieldDto] = None + typegen__date_field_dto: Optional[DateFieldDto] = None + typegen__integer_field_dto: Optional[IntegerFieldDto] = None + typegen__geolocation_field_dto: Optional[GeolocationFieldDto] = None + typegen__tags_field_dto: Optional[TagsFieldDto] = None + typegen__file_field_dto: Optional[FileFieldDto] = None + typegen__taxonomy_selection_field_dto: Optional[TaxonomySelectionFieldDto] = None + typegen__collection_selection_field_dto: Optional[CollectionSelectionFieldDto] = None + typegen__user_selection_field_dto: Optional[UserSelectionFieldDto] = None + typegen__role_selection_field_dto: Optional[RoleSelectionFieldDto] = None + typegen__enum_selection_field_dto: Optional[EnumSelectionFieldDto] = None + typegen__object_field_dto: Optional[ObjectFieldDto] = None + typegen__array_field_dto: Optional[ArrayFieldDto] = None + typegen__json_field_dto: Optional[JsonFieldDto] = None + + # @Route("/{version}/echo", "GET") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass @@ -1400,45 +1696,55 @@ class SaveGuestUser(SaveUser, IReturn[IdResponse]): pass -# @Route("/{version}/membership/auth/register/user-name", "POST") +# @Route("/{version}/membership/auth/register/phone", "POST") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class SaveUserNameUser(SaveUser, IReturn[IdResponse]): +class SavePhoneUser(SaveUser, IReturn[IdResponse]): """ Membership """ - password: Optional[str] = None - user_name: Optional[str] = None + # @ApiMember(Description="Phone number for the new user, in E.164 format.", IsRequired=true) + phone: Optional[str] = None + """ + Phone number for the new user, in E.164 format. + """ -# @Route("/{version}/membership/auth/register/email", "POST") +# @Route("/{version}/membership/auth/register/user-name", "POST") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class SaveEmailUser(SaveUser, IReturn[IdResponse]): +class SaveUserNameUser(SaveUser, IReturn[IdResponse], IPublicRegistrationRequest): """ Membership """ password: Optional[str] = None - email: Optional[str] = None + user_name: Optional[str] = None + # @ApiMember(Description="Optional roles from the project's \"Permitted user registration roles\". Empty = the default registration role.") + roles: Optional[List[str]] = None + """ + Optional roles from the project's "Permitted user registration roles". Empty = the default registration role. + """ -# @Route("/{version}/membership/auth/register/phone", "POST") +# @Route("/{version}/membership/auth/register/email", "POST") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class SavePhoneUser(SaveUser, IReturn[IdResponse]): +class SaveEmailUser(SaveUser, IReturn[IdResponse], IPublicRegistrationRequest): """ Membership """ - # @ApiMember(Description="Phone number for the new user, in E.164 format.", IsRequired=true) - phone: Optional[str] = None + password: Optional[str] = None + email: Optional[str] = None + # @ApiMember(Description="Optional roles from the project's \"Permitted user registration roles\". Empty = the default registration role.") + roles: Optional[List[str]] = None """ - Phone number for the new user, in E.164 format. + Optional roles from the project's "Permitted user registration roles". Empty = the default registration role. """ @@ -1584,6 +1890,41 @@ class GetUsersRequest(CodeMashListPaginationRequestBase, IReturn[GetUsersRespons """ + # @ApiMember(Description="Free text, case-insensitive: matches email, user name, display / first / last name or phone.") + search: Optional[str] = None + """ + Free text, case-insensitive: matches email, user name, display / first / last name or phone. + """ + + + # @ApiMember(Description="Case-insensitive part of the email.") + email: Optional[str] = None + """ + Case-insensitive part of the email. + """ + + + # @ApiMember(Description="Case-insensitive part of the user name.") + user_name: Optional[str] = None + """ + Case-insensitive part of the user name. + """ + + + # @ApiMember(Description="Status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked.") + statuses: Optional[List[str]] = None + """ + Status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked. + """ + + + # @ApiMember(Description="Login type names, any of: Service, Email, UserName, Phone, Guest, Social.") + types: Optional[List[str]] = None + """ + Login type names, any of: Service, Email, UserName, Phone, Guest, Social. + """ + + # @Route("/{version}/membership/auth/{id}/preferences", "GET") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -1655,10 +1996,24 @@ class InviteUserRequest(CodeMashRequestBase, IReturn[EmptyResponse]): Membership """ - # @ApiMember(Description="Email address the invitation is sent to.", IsRequired=true) + # @ApiMember(Description="Email address the invitation is sent to. It cannot be changed later.", IsRequired=true) email: Optional[str] = None """ - Email address the invitation is sent to. + Email address the invitation is sent to. It cannot be changed later. + """ + + + # @ApiMember(Description="The invited person's full name, e.g. \"Rūta Petraitė\". Stored as the full name, first name (first word) and last name (the rest). The user may change it when finishing.") + full_name: Optional[str] = None + """ + The invited person's full name, e.g. "Rūta Petraitė". Stored as the full name, first name (first word) and last name (the rest). The user may change it when finishing. + """ + + + # @ApiMember(Description="Optional. How e-mails greet the person (\"Hi {salutation},\"), e.g. \"Rūta\". Stored as the display name. When empty the full name is used. The user may change it when finishing.") + salutation: Optional[str] = None + """ + Optional. How e-mails greet the person ("Hi {salutation},"), e.g. "Rūta". Stored as the display name. When empty the full name is used. The user may change it when finishing. """ @@ -1669,6 +2024,64 @@ class InviteUserRequest(CodeMashRequestBase, IReturn[EmptyResponse]): """ +# @Route("/{version}/membership/auth/invitation/finish", "POST") +# @Api(Description="Membership") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class FinishInvitationRequest(CodeMashRequestBase, IReturn[EmptyResponse]): + """ + Membership + """ + + # @ApiMember(Description="One-time invitation token from the e-mail link (the #token= fragment).", IsRequired=true) + token: Optional[str] = None + """ + One-time invitation token from the e-mail link (the #token= fragment). + """ + + + # @ApiMember(Description="The user's password. Validated against the project's complexity policy.", IsRequired=true) + password: Optional[str] = None + """ + The user's password. Validated against the project's complexity policy. + """ + + + # @ApiMember(Description="Optional. The user's full name; replaces the one the admin entered (full name, first name = first word, last name = the rest). Empty = keep the admin's.") + full_name: Optional[str] = None + """ + Optional. The user's full name; replaces the one the admin entered (full name, first name = first word, last name = the rest). Empty = keep the admin's. + """ + + + # @ApiMember(Description="Optional. How e-mails greet the user (stored as the display name). Empty = keep the admin's, or the full name when the admin gave none.") + salutation: Optional[str] = None + """ + Optional. How e-mails greet the user (stored as the display name). Empty = keep the admin's, or the full name when the admin gave none. + """ + + + # @ApiMember(Description="Optional. Older form of Salutation (the display name); Salutation wins when both are sent.") + display_name: Optional[str] = None + """ + Optional. Older form of Salutation (the display name); Salutation wins when both are sent. + """ + + + # @ApiMember(Description="Optional first name; wins over the one taken from FullName.") + first_name: Optional[str] = None + """ + Optional first name; wins over the one taken from FullName. + """ + + + # @ApiMember(Description="Optional last name; wins over the one taken from FullName.") + last_name: Optional[str] = None + """ + Optional last name; wins over the one taken from FullName. + """ + + # @Route("/{version}/membership/auth/{userId}/link-identity", "POST") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -2192,7 +2605,13 @@ class FindMergedTermTreeRequest(CodeMashRequestBase, IReturn[FindMergedTermTreeR """ + # @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) taxonomy_name: Optional[str] = None + """ + The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). + """ + + database_integration_id: Optional[str] = None @@ -2232,7 +2651,13 @@ class FindTermsRequest(CodeMashListPaginationRequestBase, IReturn[FindTermsRespo """ + # @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) taxonomy_name: Optional[str] = None + """ + The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). + """ + + database_integration_id: Optional[str] = None filter: Optional[str] = None sort_descending: bool = False @@ -2255,7 +2680,13 @@ class FindTermsChildrenRequest(CodeMashListPaginationRequestBase, IReturn[FindTe """ + # @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) taxonomy_name: Optional[str] = None + """ + The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). + """ + + parent_id: Optional[str] = None database_integration_id: Optional[str] = None filter: Optional[str] = None @@ -2278,7 +2709,13 @@ class FindTermTreeRequest(CodeMashRequestBase, IReturn[FindTermTreeResponse]): """ + # @ApiMember(Description="The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…).", IsRequired=true) taxonomy_name: Optional[str] = None + """ + The taxonomy: its name (slug or title; URL-encode spaces) or its id (txn_…). + """ + + root_term_id: Optional[str] = None depth: Optional[int] = None database_integration_id: Optional[str] = None @@ -2746,10 +3183,10 @@ class RegisterOwnPushDeviceRequest(CodeMashRequestBase, IReturn[IdResponse]): Registers or refreshes a push device for the signed-in user. """ - # @ApiMember(Description="Who issued the token: expo (getExpoPushTokenAsync), fcm (Android / Firebase) or apns (iOS).", IsRequired=true) + # @ApiMember(Description="Who issued the token: fcm (Android / Firebase) or apns (iOS). The NATIVE device token — in an Expo app use getDevicePushTokenAsync(). Expo push tokens (provider 'expo') are refused.", IsRequired=true) provider: Optional[str] = None """ - Who issued the token: expo (getExpoPushTokenAsync), fcm (Android / Firebase) or apns (iOS). + Who issued the token: fcm (Android / Firebase) or apns (iOS). The NATIVE device token — in an Expo app use getDevicePushTokenAsync(). Expo push tokens (provider 'expo') are refused. """ @@ -2912,3 +3349,187 @@ class MarkAllOwnPushMessagesReadRequest(CodeMashRequestBase, IReturn[EmptyRespon pass + +# @Route("/{version}/payments/orders", "POST") +# @Api(Description="Stores a payment order with a fixed price for one of the project's users. Server only (service user API key).") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CreatePaymentOrderRequest(CodeMashRequestBase, IReturn[IdResponse]): + """ + Stores a payment order with a fixed price for one of the project's users. Server only (service user API key). + """ + + # @ApiMember(Description="The user the order is for (usr_…).", IsRequired=true) + buyer_user_id: Optional[str] = None + """ + The user the order is for (usr_…). + """ + + + # @ApiMember(Description="The project's own order reference, unique per project and environment (1–64 of A–Z a–z 0–9 . _ : -).", IsRequired=true) + merchant_reference: Optional[str] = None + """ + The project's own order reference, unique per project and environment (1–64 of A–Z a–z 0–9 . _ : -). + """ + + + # @ApiMember(Description="8–128 characters. Same key + same body = the stored order; same key + other body = 409. May be sent as the Idempotency-Key header instead.") + idempotency_key: Optional[str] = None + """ + 8–128 characters. Same key + same body = the stored order; same key + other body = 409. May be sent as the Idempotency-Key header instead. + """ + + + # @ApiMember(Description="EUR.", IsRequired=true) + currency: Optional[str] = None + """ + EUR. + """ + + + # @ApiMember(Description="The version of the price list the server priced the lines with.", IsRequired=true) + price_version: Optional[str] = None + """ + The version of the price list the server priced the lines with. + """ + + + # @ApiMember(Description="1–50 lines: sku, title, quantity, unitAmountMinor (cents). Norbix computes the amounts and the total.", IsRequired=true) + lines: List[PaymentOrderLineInput] = field(default_factory=list) + """ + 1–50 lines: sku, title, quantity, unitAmountMinor (cents). Norbix computes the amounts and the total. + """ + + + # @ApiMember(Description="Up to 20 project values (e.g. adId). No personal or billing data.") + metadata: Optional[Dict[str, str]] = None + """ + Up to 20 project values (e.g. adId). No personal or billing data. + """ + + +# @Route("/{version}/payments/orders/{Id}", "GET") +# @Api(Description="Reads one payment order. A buyer reads only their own orders.") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetPaymentOrderRequest(CodeMashRequestBase, IReturn[GetPaymentOrderResponse]): + """ + Reads one payment order. A buyer reads only their own orders. + """ + + # @ApiMember(Description="The order id (ord_…).", IsRequired=true) + id: Optional[str] = None + """ + The order id (ord_…). + """ + + +# @Route("/{version}/payments/orders", "GET") +# @Api(Description="Lists payment orders, newest first. A buyer gets only their own orders.") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetPaymentOrdersRequest(CodeMashListPaginationRequestBase, IReturn[GetPaymentOrdersResponse]): + """ + Lists payment orders, newest first. A buyer gets only their own orders. + """ + + # @ApiMember(Description="Server only: one buyer's orders (usr_…). A buyer always gets their own.") + buyer_user_id: Optional[str] = None + """ + Server only: one buyer's orders (usr_…). A buyer always gets their own. + """ + + + # @ApiMember(Description="Only the order with this merchant reference.") + merchant_reference: Optional[str] = None + """ + Only the order with this merchant reference. + """ + + + # @ApiMember(Description="Only orders in this status (Created, CheckoutStarted, Paid, …).") + status: Optional[str] = None + """ + Only orders in this status (Created, CheckoutStarted, Paid, …). + """ + + +# @Route("/{version}/payments/orders/{Id}/checkout", "POST") +# @Api(Description="Opens a Montonio checkout for a stored order and answers where the buyer pays. The buyer (own order) or the server.") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class StartPaymentCheckoutRequest(CodeMashRequestBase, IReturn[StartPaymentCheckoutResponse]): + """ + Opens a Montonio checkout for a stored order and answers where the buyer pays. The buyer (own order) or the server. + """ + + # @ApiMember(Description="The order id (ord_…).", IsRequired=true) + id: Optional[str] = None + """ + The order id (ord_…). + """ + + + # @ApiMember(Description="The Montonio integration (int_…) of the project in the request's environment.", IsRequired=true) + integration_id: Optional[str] = None + """ + The Montonio integration (int_…) of the project in the request's environment. + """ + + + # @ApiMember(Description="bankLink (default), card, applePay or googlePay.") + method: Optional[str] = None + """ + bankLink (default), card, applePay or googlePay. + """ + + + # @ApiMember(Description="Where the buyer comes back after paying; its origin must be one of the project's allowed origins.", IsRequired=true) + return_url: Optional[str] = None + """ + Where the buyer comes back after paying; its origin must be one of the project's allowed origins. + """ + + + # @ApiMember(Description="Bank links only: the country whose banks are shown first (default LT).") + preferred_country: Optional[str] = None + """ + Bank links only: the country whose banks are shown first (default LT). + """ + + + # @ApiMember(Description="Bank links only: one bank to open directly (the provider's bank code).") + preferred_provider: Optional[str] = None + """ + Bank links only: one bank to open directly (the provider's bank code). + """ + + +# @Route("/{version}/notifications/inbox", "GET") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetNotificationInboxRequest(CodeMashListPaginationRequestBase, IReturn[GetNotificationInboxResponse]): + unread_only: bool = False + channel: Optional[str] = None + + +# @Route("/{version}/notifications/inbox/unread-count", "GET") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetUnreadCountRequest(CodeMashRequestBase, IReturn[GetUnreadCountResponse]): + pass + + +# @Route("/{version}/notifications/inbox/{notificationId}/read", "POST") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkNotificationReadRequest(CodeMashRequestBase, IReturn[MarkNotificationReadResponse]): + notification_id: Optional[str] = None + + +# @Route("/{version}/notifications/inbox/read-all", "POST") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkAllNotificationsReadRequest(CodeMashRequestBase, IReturn[MarkAllNotificationsReadResponse]): + pass + diff --git a/references/hub2.dtos.ts b/references/hub2.dtos.ts index 5739242..b13c5e9 100644 --- a/references/hub2.dtos.ts +++ b/references/hub2.dtos.ts @@ -1,5 +1,5 @@ /* Options: -Date: 2026-10-14 08:01:42 +Date: 2026-10-19 11:26:14 Version: 10.20 Tip: To override a DTO option, remove "//" prefix before updating BaseUrl: http://localhost:5001 @@ -338,6 +338,9 @@ export enum SchemaTriggerType OnInserted = 'OnInserted', OnDeleted = 'OnDeleted', OnUpdated = 'OnUpdated', + OnInsertedMany = 'OnInsertedMany', + OnUpdatedMany = 'OnUpdatedMany', + OnDeletedMany = 'OnDeletedMany', } export class SchemaTriggerRequest extends SaveTriggerRequest @@ -370,6 +373,7 @@ export enum PaymentTriggerType OnOrderCreated = 'OnOrderCreated', OnOrderPaid = 'OnOrderPaid', OnWebhookCallReceived = 'OnWebhookCallReceived', + OnOrderPaymentChanged = 'OnOrderPaymentChanged', } export class PaymentTriggerRequest extends SaveTriggerRequest @@ -888,6 +892,7 @@ export enum PaymentGatewayPlatform CheckOutCom = 'CheckOutCom', Mollie = 'Mollie', Worldpay = 'Worldpay', + Montonio = 'Montonio', } export class PaymentIntegrationRequest @@ -997,6 +1002,88 @@ export class GoogleInAppPaymentIntegrationRequest extends PaymentIntegrationRequ public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class MontonioPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public accessKey: string; + public secretKey: string; + public isSandbox: boolean; + public locale?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class ShopifyPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public shopDomain: string; + public webhookSecret: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class WooCommercePaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public storeUrl: string; + public webhookSecret: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class MagentoPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public storeUrl: string; + public webhookSecret: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class BraintreePaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public merchantId: string; + public environment: string; + public privateKey: string; + public webhookSecret?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class AuthorizeNetPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public merchantLoginId: string; + public environment: string; + public transactionKey: string; + public webhookSignatureKey?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class CheckOutComPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public merchantAccount: string; + public environment: string; + public secretKey: string; + public webhookSecret?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class WorldpayPaymentIntegrationRequest extends PaymentIntegrationRequest +{ + public provider: PaymentGatewayPlatform; + public merchantCode: string; + public environment: string; + public apiKey: string; + public webhookSecret?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + // @DataContract export enum PushProvider { @@ -2121,6 +2208,9 @@ export class EmailToCollectionRecordsDeliverySettingsDto extends EmailCampaignDe // @DataMember public languages?: string[]; + // @DataMember + public recordIds?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -2187,6 +2277,9 @@ export class PushToCollectionRecordsDeliverySettingsDto extends PushCampaignDeli // @DataMember public languages?: string[]; + // @DataMember + public recordIds?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -2259,6 +2352,9 @@ export class SmsToCollectionRecordsDeliverySettingsDto extends SmsCampaignDelive // @DataMember public languages?: string[]; + // @DataMember + public recordIds?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -2583,6 +2679,173 @@ export class WorldpayPaymentIntegrationDto extends PaymentsIntegrationDto public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class MontonioPaymentIntegrationDto extends PaymentsIntegrationDto +{ + public accessKey: string; + public isSandbox: boolean; + public locale?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +// @DataContract +export class PaymentOrderLineDto +{ + // @DataMember + public sku: string; + + // @DataMember + public title: string; + + // @DataMember + public quantity: number; + + // @DataMember + public unitAmountMinor: number; + + // @DataMember + public amountMinor: number; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class PaymentOrderCheckoutDto +{ + // @DataMember + public attempt: number; + + // @DataMember + public integrationId: string; + + // @DataMember + public provider: string; + + // @DataMember + public providerOrderId: string; + + // @DataMember + public providerReference: string; + + // @DataMember + public paymentUrl: string; + + // @DataMember + public method: string; + + // @DataMember + public startedOnUtc: string; + + // @DataMember + public expiresAtUtc: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class PaymentOrderDto +{ + // @DataMember + public id: string; + + // @DataMember + public env: string; + + // @DataMember + public buyerUserId: string; + + // @DataMember + public merchantReference: string; + + // @DataMember + public currency: string; + + // @DataMember + public priceVersion: string; + + // @DataMember + public lines: PaymentOrderLineDto[] = []; + + // @DataMember + public totalMinor: number; + + // @DataMember + public metadata: { [index:string]: string; } = {}; + + // @DataMember + public status: string; + + // @DataMember + public createdOnUtc: string; + + // @DataMember + public updatedOnUtc: string; + + // @DataMember + public checkouts: PaymentOrderCheckoutDto[] = []; + + // @DataMember + public settledMinor?: number; + + // @DataMember + public refundedMinor: number; + + // @DataMember + public paidOnUtc?: string; + + // @DataMember + public providerPaymentId?: string; + + // @DataMember + public mismatches: string[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class PaymentEventDto +{ + public integrationId: string; + public provider: string; + public providerEventId: string; + public orderId?: string; + public eventName: string; + public status: string; + public amountMinor?: number; + public currency?: string; + public externalIds?: { [index:string]: string; }; + public occurredOn?: string; + public receivedOn: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class PaymentOrderEventDto +{ + // @DataMember + public orderEventId: string; + + // @DataMember + public event: string; + + // @DataMember + public from: string; + + // @DataMember + public to: string; + + // @DataMember + public reason: string; + + // @DataMember + public order: PaymentOrderDto; + + // @DataMember + public payment: PaymentEventDto; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + export class MembershipIntegrationDto extends IntegrationDto { public provider: MembershipProvider; @@ -3190,6 +3453,12 @@ export class SchedulerTaskDto // @DataMember public updatedAtUnix?: number; + // @DataMember + public endsAtUnix?: number; + + // @DataMember + public hasEnded: boolean; + // @DataMember public isFailing: boolean; @@ -3227,6 +3496,9 @@ export class IdResponse extends ResponseBase // @DataMember public status?: string; + // @DataMember + public warnings?: string[]; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -4023,631 +4295,658 @@ export class ConversationSnapshotEntryWireDto extends AiChatEntryWireDto public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class JsonSchemaFieldDto +export enum CodeFunctionSource { - // @DataMember - public fieldName: string; + Database = 'Database', + Membership = 'Membership', + Files = 'Files', + Payments = 'Payments', + Ai = 'Ai', + Scheduler = 'Scheduler', + Manual = 'Manual', +} - public constructor(init?: Partial) { (Object as any).assign(this, init); } +export enum CodeFunctionCallerKind +{ + User = 'User', + ApiKey = 'ApiKey', + System = 'System', } -export class StringFieldDto extends JsonSchemaFieldDto +// @DataContract +export class CodeFunctionCallerDto { // @DataMember - public format?: string; + public userId: string; // @DataMember - public pattern?: string; + public email?: string; // @DataMember - public minLength?: number; + public kind: CodeFunctionCallerKind; - // @DataMember - public maxLength?: number; + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} +// @DataContract +export class CodeFunctionRunAsDto +{ // @DataMember - public translateOptions?: IReadOnlyDictionary; + public userId: string; // @DataMember - public default?: string; + public accessToken?: string; // @DataMember - public unique?: boolean; + public expiresAt?: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class DecimalFieldDto extends JsonSchemaFieldDto +// @DataContract +export class CodeFunctionContextDto { // @DataMember - public minimum?: number; + public accountId: string; // @DataMember - public maximum?: number; + public projectId: string; // @DataMember - public multipleOf?: number; + public environment: string; // @DataMember - public default?: number; + public region?: string; // @DataMember - public unique?: boolean; + public hubUrl: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} - -export class CurrencyDefaultDto -{ // @DataMember - public value: number; + public apiUrl: string; // @DataMember - public currency: string; - - public constructor(init?: Partial) { (Object as any).assign(this, init); } -} + public echoUrl: string; -export class CurrencyFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public allowedCurrencies?: IReadOnlyList; + public triggerId?: string; // @DataMember - public multipleOf?: number; + public taskId?: string; // @DataMember - public minimum?: number; + public correlationId?: string; // @DataMember - public maximum?: number; + public caller?: CodeFunctionCallerDto; // @DataMember - public default?: CurrencyDefaultDto; + public runAs?: CodeFunctionRunAsDto; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class BooleanFieldDto extends JsonSchemaFieldDto +export enum ResourceKindDto { - // @DataMember - public default?: boolean; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + Contact = 'contact', + Document = 'document', + File = 'file', + PaymentCustomer = 'paymentCustomer', + Order = 'order', + Payment = 'payment', + Product = 'product', + Integration = 'integration', } -export class DateFieldDto extends JsonSchemaFieldDto +export class ResourceRefDto { - // @DataMember - public minimum?: number; + public projectId: string; + public integrationId?: string; + public kind: ResourceKindDto; - // @DataMember - public maximum?: number; + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} - // @DataMember - public default?: number; +export class DocumentRefDto extends ResourceRefDto +{ + public kind: ResourceKindDto; + public databaseIntegrationId: string; + public schemaId: string; + public externalId: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class IntegerFieldDto extends JsonSchemaFieldDto +// @DataContract +export class DatabaseRecordsBatchDto { // @DataMember - public minimum?: number; + public ids: string[] = []; // @DataMember - public maximum?: number; + public count: number; // @DataMember - public default?: number; + public truncated: boolean; // @DataMember - public unique?: boolean; + public documents?: { [index:string]: Object; }[]; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class GeolocationFieldDto extends JsonSchemaFieldDto +// @DataContract +export class DatabaseRecordChangeDto { // @DataMember - public allowedTypes?: IReadOnlyList; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public collection: string; -export class TagsFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public minItems?: number; + public schemaId: string; // @DataMember - public maxItems?: number; + public schemaVersion?: number; // @DataMember - public default?: IReadOnlyList; + public recordId?: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + // @DataMember + public old?: { [index:string]: Object; }; -export class FileFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public storages?: IReadOnlyList; + public new?: { [index:string]: Object; }; // @DataMember - public minItems?: number; + public truncated: boolean; // @DataMember - public maxItems?: number; + public oldRef?: DocumentRefDto; // @DataMember - public allowedFileType?: string; + public newRef?: DocumentRefDto; // @DataMember - public maxSizeMb?: number; + public records?: DatabaseRecordsBatchDto; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class TaxonomySelectionFieldDto extends JsonSchemaFieldDto +// @DataContract +export class UserChangeDto { // @DataMember - public taxonomyId?: string; + public userId: string; // @DataMember - public multiple: boolean; + public old?: { [index:string]: Object; }; // @DataMember - public displayField?: string; + public new?: { [index:string]: Object; }; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class CollectionSelectionFieldDto extends JsonSchemaFieldDto +// @DataContract +export class FileChangeDto { // @DataMember - public collectionId?: string; - - // @DataMember - public displayField?: string; - - // @DataMember - public multiple: boolean; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public old?: { [index:string]: Object; }; -export class UserSelectionFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public multiple: boolean; + public new?: { [index:string]: Object; }; // @DataMember - public displayField?: string; + public path?: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class RoleSelectionFieldDto extends JsonSchemaFieldDto +// @DataContract +export class PaymentFactDto { // @DataMember - public multiple: boolean; + public integrationId: string; // @DataMember - public displayField?: string; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public provider: string; -export class EnumSelectionFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public values?: IReadOnlyList; + public providerEventId: string; // @DataMember - public multiple: boolean; + public orderId?: string; // @DataMember - public default?: IReadOnlyList; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public eventName: string; -export class ObjectFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public properties: IReadOnlyList; + public status: string; // @DataMember - public required?: IReadOnlyList; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public amountMinor?: number; -export class ArrayFieldDto extends JsonSchemaFieldDto -{ // @DataMember - public items: JsonSchemaFieldDto; + public currency?: string; // @DataMember - public minItems?: number; + public externalIds?: { [index:string]: string; }; // @DataMember - public maxItems?: number; + public occurredOn?: string; // @DataMember - public uniqueItems?: boolean; + public receivedOn: string; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export class JsonFieldDto extends JsonSchemaFieldDto +// @DataContract +export class AiUsageEventDto { // @DataMember - public maxBytes?: number; - - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + public payload: { [index:string]: Object; } = {}; -export enum CodeFunctionSource -{ - Database = 'Database', - Membership = 'Membership', - Files = 'Files', - Payments = 'Payments', - Ai = 'Ai', - Scheduler = 'Scheduler', - Manual = 'Manual', -} + // @DataMember + public targetUserId?: string; -export enum CodeFunctionCallerKind -{ - User = 'User', - ApiKey = 'ApiKey', - System = 'System', + public constructor(init?: Partial) { (Object as any).assign(this, init); } } // @DataContract -export class CodeFunctionCallerDto +export class ScheduledTaskInfoDto { // @DataMember - public userId: string; + public taskId: string; // @DataMember - public email?: string; + public name: string; // @DataMember - public kind: CodeFunctionCallerKind; + public firedAt: string; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { (Object as any).assign(this, init); } } // @DataContract -export class CodeFunctionRunAsDto +export class MarketplaceFunctionCallDto { // @DataMember - public userId: string; + public functionId: string; // @DataMember - public accessToken?: string; + public functionKey: string; // @DataMember - public expiresAt?: string; + public integrationId: string; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + // @DataMember + public payload: { [index:string]: Object; } = {}; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } } // @DataContract -export class CodeFunctionContextDto +export class CodeFunctionDataDto { // @DataMember - public accountId: string; + public database?: DatabaseRecordChangeDto; // @DataMember - public projectId: string; + public user?: UserChangeDto; // @DataMember - public environment: string; + public file?: FileChangeDto; // @DataMember - public region?: string; + public payment?: PaymentFactDto; // @DataMember - public hubUrl: string; + public order?: PaymentOrderEventDto; // @DataMember - public apiUrl: string; + public ai?: AiUsageEventDto; // @DataMember - public echoUrl: string; + public task?: ScheduledTaskInfoDto; // @DataMember - public triggerId?: string; + public payload?: { [index:string]: Object; }; // @DataMember - public taskId?: string; + public marketplace?: MarketplaceFunctionCallDto; + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class CodeFunctionEventDto +{ // @DataMember - public correlationId?: string; + public specVersion: string; // @DataMember - public caller?: CodeFunctionCallerDto; + public id: string; // @DataMember - public runAs?: CodeFunctionRunAsDto; + public eventId: string; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + // @DataMember + public event: string; + + // @DataMember + public source: CodeFunctionSource; + + // @DataMember + public createdOn: string; + + // @DataMember + public context: CodeFunctionContextDto; + + // @DataMember + public data: CodeFunctionDataDto; + + // @DataMember + public config?: { [index:string]: Object; }; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export enum ResourceKindDto +export class FakeCodeIntegrationDto extends CodeIntegrationDto { - Contact = 'contact', - Document = 'document', - File = 'file', - PaymentCustomer = 'paymentCustomer', - Order = 'order', - Payment = 'payment', - Product = 'product', - Integration = 'integration', + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class ResourceRefDto +export class FakeCodeIntegrationRequest extends CodeIntegrationRequest { - public projectId: string; - public integrationId?: string; - public kind: ResourceKindDto; + public provider: CodeProvider; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class DocumentRefDto extends ResourceRefDto +export class CodeFunctionSchedulerTaskRequest extends SchedulerTaskRequest { - public kind: ResourceKindDto; - public databaseIntegrationId: string; - public schemaId: string; - public externalId: string; + public type: SchedulerTaskType; + public functionRef?: FunctionRefDto; + public invocationType: CodeInvocationType; + public config?: string; + public mappedTokens?: TokenMappingDto[]; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class DatabaseRecordChangeDto +export class MarketplaceFunctionSchedulerTaskRequest extends SchedulerTaskRequest { - // @DataMember - public collection: string; + public type: SchedulerTaskType; + public functionId?: string; + public payload?: { [index:string]: string; }; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} +export class JsonSchemaFieldDto +{ // @DataMember - public schemaId: string; + public fieldName: string; + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class StringFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public schemaVersion?: number; + public format?: string; // @DataMember - public recordId?: string; + public pattern?: string; // @DataMember - public old?: { [index:string]: Object; }; + public minLength?: number; // @DataMember - public new?: { [index:string]: Object; }; + public maxLength?: number; // @DataMember - public truncated: boolean; + public translateOptions?: IReadOnlyDictionary; // @DataMember - public oldRef?: DocumentRefDto; + public default?: string; // @DataMember - public newRef?: DocumentRefDto; + public unique?: boolean; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class UserChangeDto +export class DecimalFieldDto extends JsonSchemaFieldDto { // @DataMember - public userId: string; - - // @DataMember - public old?: { [index:string]: Object; }; + public minimum?: number; // @DataMember - public new?: { [index:string]: Object; }; - - public constructor(init?: Partial) { (Object as any).assign(this, init); } -} + public maximum?: number; -// @DataContract -export class FileChangeDto -{ // @DataMember - public old?: { [index:string]: Object; }; + public multipleOf?: number; // @DataMember - public new?: { [index:string]: Object; }; + public default?: number; // @DataMember - public path?: string; + public unique?: boolean; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class PaymentFactDto +export class CurrencyDefaultDto { // @DataMember - public integrationId: string; + public value: number; // @DataMember - public provider: string; + public currency: string; - // @DataMember - public providerEventId: string; + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} +export class CurrencyFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public eventName: string; + public allowedCurrencies?: IReadOnlyList; // @DataMember - public status: string; + public multipleOf?: number; // @DataMember - public amountMinor?: number; + public minimum?: number; // @DataMember - public currency?: string; + public maximum?: number; // @DataMember - public externalIds?: { [index:string]: string; }; + public default?: CurrencyDefaultDto; - // @DataMember - public occurredOn?: string; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} +export class BooleanFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public receivedOn: string; + public default?: boolean; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class AiUsageEventDto +export class DateFieldDto extends JsonSchemaFieldDto { // @DataMember - public payload: { [index:string]: Object; } = {}; + public minimum?: number; // @DataMember - public targetUserId?: string; + public maximum?: number; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + // @DataMember + public default?: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class ScheduledTaskInfoDto +export class IntegerFieldDto extends JsonSchemaFieldDto { // @DataMember - public taskId: string; + public minimum?: number; // @DataMember - public name: string; + public maximum?: number; // @DataMember - public firedAt: string; + public default?: number; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + // @DataMember + public unique?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class MarketplaceFunctionCallDto +export class GeolocationFieldDto extends JsonSchemaFieldDto { // @DataMember - public functionId: string; + public allowedTypes?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} +export class TagsFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public functionKey: string; + public minItems?: number; // @DataMember - public integrationId: string; + public maxItems?: number; // @DataMember - public payload: { [index:string]: Object; } = {}; + public default?: IReadOnlyList; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class CodeFunctionDataDto +export class FileFieldDto extends JsonSchemaFieldDto { // @DataMember - public database?: DatabaseRecordChangeDto; + public storages?: IReadOnlyList; // @DataMember - public user?: UserChangeDto; + public minItems?: number; // @DataMember - public file?: FileChangeDto; + public maxItems?: number; // @DataMember - public payment?: PaymentFactDto; + public allowedFileType?: string; // @DataMember - public ai?: AiUsageEventDto; + public maxSizeMb?: number; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class TaxonomySelectionFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public task?: ScheduledTaskInfoDto; + public taxonomyId?: string; // @DataMember - public payload?: { [index:string]: Object; }; + public multiple: boolean; // @DataMember - public marketplace?: MarketplaceFunctionCallDto; + public displayField?: string; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -// @DataContract -export class CodeFunctionEventDto +export class CollectionSelectionFieldDto extends JsonSchemaFieldDto { // @DataMember - public specVersion: string; + public collectionId?: string; // @DataMember - public id: string; + public displayField?: string; // @DataMember - public eventId: string; + public multiple: boolean; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class UserSelectionFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public event: string; + public multiple: boolean; // @DataMember - public source: CodeFunctionSource; + public displayField?: string; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class RoleSelectionFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public createdOn: string; + public multiple: boolean; // @DataMember - public context: CodeFunctionContextDto; + public displayField?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} +export class EnumSelectionFieldDto extends JsonSchemaFieldDto +{ // @DataMember - public data: CodeFunctionDataDto; + public values?: IReadOnlyList; // @DataMember - public config?: { [index:string]: Object; }; + public multiple: boolean; - public constructor(init?: Partial) { (Object as any).assign(this, init); } + // @DataMember + public default?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class FakeCodeIntegrationDto extends CodeIntegrationDto +export class ObjectFieldDto extends JsonSchemaFieldDto { + // @DataMember + public properties: IReadOnlyList; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + // @DataMember + public required?: IReadOnlyList; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class FakeCodeIntegrationRequest extends CodeIntegrationRequest +export class ArrayFieldDto extends JsonSchemaFieldDto { - public provider: CodeProvider; + // @DataMember + public items: JsonSchemaFieldDto; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } -} + // @DataMember + public minItems?: number; -export class CodeFunctionSchedulerTaskRequest extends SchedulerTaskRequest -{ - public type: SchedulerTaskType; - public functionRef?: FunctionRefDto; - public invocationType: CodeInvocationType; - public config?: string; - public mappedTokens?: TokenMappingDto[]; + // @DataMember + public maxItems?: number; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + // @DataMember + public uniqueItems?: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } -export class MarketplaceFunctionSchedulerTaskRequest extends SchedulerTaskRequest +export class JsonFieldDto extends JsonSchemaFieldDto { - public type: SchedulerTaskType; - public functionId?: string; - public payload?: { [index:string]: string; }; + // @DataMember + public maxBytes?: number; - public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } export interface IVersionBasedRequest @@ -4881,6 +5180,81 @@ export class AiProjectRoleIdsDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +export enum Gender +{ + Male = 'Male', + Female = 'Female', + Other = 'Other', +} + +export enum MarketingBlockReason +{ + Unspecified = 'Unspecified', + Unsubscribed = 'Unsubscribed', + Complaint = 'Complaint', + HardBounce = 'HardBounce', + InvalidEmail = 'InvalidEmail', + AdminBlock = 'AdminBlock', +} + +export class UserGeneralInfoDto +{ + public phone?: string; + public primaryEmail?: string; + public displayName?: string; + public firstName?: string; + public lastName?: string; + public fullName?: string; + public addressLine1?: string; + public addressLine2?: string; + public country?: string; + public city?: string; + public state?: string; + public postalCode?: string; + public company?: string; + public gender?: Gender; + public birthDate?: number; + public timeZone?: string; + public language?: string; + public blockAllMarketingMessages: boolean; + public blockedTags?: { [index:string]: HashSet; }; + public blockReasons?: MarketingBlockReason[]; + public extraMetadata?: string; + public notes?: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class ImportUserRowDto +{ + // @DataMember(Name="email") + public email?: string; + + // @DataMember(Name="userName") + public userName?: string; + + // @DataMember(Name="userGeneralInfo") + public userGeneralInfo?: UserGeneralInfoDto; + + // @DataMember(Name="roles") + public roles?: string[]; + + // @DataMember(Name="createdOn") + public createdOn?: number; + + // @DataMember(Name="hashFormat") + public hashFormat?: string; + + // @DataMember(Name="passwordHash") + public passwordHash?: string; + + // @DataMember(Name="passwordSalt") + public passwordSalt?: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + // @DataContract export class DeleteTrigger extends CodeMashRequestBase { @@ -4969,6 +5343,14 @@ export class PagingArgs public constructor(init?: Partial) { (Object as any).assign(this, init); } } +export class SchemaUniqueIndexDto +{ + // @DataMember + public fields: string[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + export class SchemaSettingsDto { // @DataMember @@ -4980,6 +5362,9 @@ export class SchemaSettingsDto // @DataMember public description?: string; + // @DataMember + public uniqueIndexes?: SchemaUniqueIndexDto[]; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -5005,6 +5390,12 @@ export class SchemaListColumnDto // @DataMember public field: string; + // @DataMember + public primary: boolean; + + // @DataMember + public linkReference: boolean; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -5027,6 +5418,9 @@ export class SchemaListSettingsDto // @DataMember public defaultSort?: SchemaListSortDto; + // @DataMember + public filters: string[] = []; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -5234,6 +5628,10 @@ export class ChatScreenContextDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +export interface INoSessionCookies +{ +} + export enum EmbeddingProvider { Voyage = 'Voyage', @@ -5418,6 +5816,16 @@ export class TriggerAttentionDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +export class TriggerActivationTestProblem +{ + public code: string; + public message: string; + public line: number; + public column: number; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + // @DataContract export class AccountOwnerDto { @@ -5594,6 +6002,24 @@ export class PromotionBlockerDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +// @DataContract +export class PromotionTermChangeDto +{ + // @DataMember + public taxonomyId: string; + + // @DataMember + public termId: string; + + // @DataMember + public slug?: string; + + // @DataMember + public change: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + // @DataContract export class PromotionResultDto { @@ -5615,6 +6041,12 @@ export class PromotionResultDto // @DataMember public blockers: PromotionBlockerDto[] = []; + // @DataMember + public termChanges: PromotionTermChangeDto[] = []; + + // @DataMember + public warnings: PromotionBlockerDto[] = []; + // @DataMember public fromVersion?: number; @@ -5996,6 +6428,9 @@ export class MembershipDto // @DataMember public customPolicies?: PolicyItemDto[]; + // @DataMember + public systemRoleAttachments?: RoleItemDto[]; + // @DataMember public authorization?: AuthorizationDto; @@ -6329,6 +6764,12 @@ export class ProjectListItemDto // @DataMember public additionalRegions?: ProjectRegionDto[]; + // @DataMember + public modulesCount: number; + + // @DataMember + public usersCount: number; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -6599,55 +7040,11 @@ export class LoginDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } -export enum Gender -{ - Male = 'Male', - Female = 'Female', - Other = 'Other', -} - -export enum MarketingBlockReason -{ - Unspecified = 'Unspecified', - Unsubscribed = 'Unsubscribed', - Complaint = 'Complaint', - HardBounce = 'HardBounce', - InvalidEmail = 'InvalidEmail', - AdminBlock = 'AdminBlock', -} - -export class UserGeneralInfoDto -{ - public phone?: string; - public primaryEmail?: string; - public displayName?: string; - public firstName?: string; - public lastName?: string; - public fullName?: string; - public addressLine1?: string; - public addressLine2?: string; - public country?: string; - public city?: string; - public state?: string; - public postalCode?: string; - public company?: string; - public gender?: Gender; - public birthDate?: number; - public timeZone?: string; - public language?: string; - public blockAllMarketingMessages: boolean; - public blockedTags?: { [index:string]: HashSet; }; - public blockReasons?: MarketingBlockReason[]; - public extraMetadata?: string; - public notes?: string; - - public constructor(init?: Partial) { (Object as any).assign(this, init); } -} - export enum AuthStatus { Registered = 0, PendingValidation = 2, + Invited = 4, Active = 8, Unregistered = 16, Suspended = 32, @@ -7018,6 +7415,96 @@ export class AiServiceUserDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +// @DataContract +export class ImportUserErrorDto +{ + // @DataMember(Name="code") + public code?: string; + + // @DataMember(Name="message") + public message: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class ImportUserOutcomeDto +{ + // @DataMember(Name="row") + public row: number; + + // @DataMember(Name="login") + public login?: string; + + // @DataMember(Name="outcome") + public outcome: string; + + // @DataMember(Name="userId") + public userId?: string; + + // @DataMember(Name="errors") + public errors: ImportUserErrorDto[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class UsersImportDto +{ + // @DataMember(Name="dryRun") + public dryRun: boolean; + + // @DataMember(Name="received") + public received: number; + + // @DataMember(Name="imported") + public imported: number; + + // @DataMember(Name="valid") + public valid: number; + + // @DataMember(Name="existing") + public existing: number; + + // @DataMember(Name="invalid") + public invalid: number; + + // @DataMember(Name="failed") + public failed: number; + + // @DataMember(Name="rows") + public rows: ImportUserOutcomeDto[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +// @DataContract +export class LoginProjectRepairDto +{ + // @DataMember(Name="dryRun") + public dryRun: boolean; + + // @DataMember(Name="loginsWithoutProject") + public loginsWithoutProject: number; + + // @DataMember(Name="loginsToRepair") + public loginsToRepair: number; + + // @DataMember(Name="loginsRepaired") + public loginsRepaired: number; + + // @DataMember(Name="accountLoginsSkipped") + public accountLoginsSkipped: number; + + // @DataMember(Name="otherProjectLoginsSkipped") + public otherProjectLoginsSkipped: number; + + // @DataMember(Name="loginsWithoutEvidence") + public loginsWithoutEvidence: number; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + export class ServiceUserApiKeyDto { public id: number; @@ -7214,37 +7701,61 @@ export class PasswordComplexityDto export class MembershipAuthorizationViewDto { // @DataMember - public emailPreferences?: MembershipEmailPreferencesDto; + public emailPreferences?: MembershipEmailPreferencesDto; + + // @DataMember + public userRegistersAsRole?: string; + + // @DataMember + public guestRegistersAsRole?: string; + + // @DataMember + public allowedRegisterRoles?: string[]; + + // @DataMember + public allowedProviderRegisterRoles?: string[]; + + // @DataMember + public resetPasswordTokenExpiration?: number; + + // @DataMember + public invitationExpiration?: number; + + // @DataMember + public emailVerificationExpiration?: number; + + // @DataMember + public deactivationExpiration?: number; // @DataMember - public userRegistersAsRole?: string; + public defaultSubscribeToNews: boolean; // @DataMember - public guestRegistersAsRole?: string; + public passwordComplexity?: PasswordComplexityDto; // @DataMember - public allowedRegisterRoles?: string[]; + public defaultRoles?: string[]; // @DataMember - public allowedProviderRegisterRoles?: string[]; + public allowedRegistrationRoles?: string[]; // @DataMember - public resetPasswordTokenExpiration?: number; + public allowGuestUsers: boolean; // @DataMember - public invitationExpiration?: number; + public guestCleanupPeriodDays?: number; // @DataMember - public emailVerificationExpiration?: number; + public allowEmailRegistration: boolean; // @DataMember - public deactivationExpiration?: number; + public allowUsernameRegistration: boolean; // @DataMember - public defaultSubscribeToNews: boolean; + public inviteOnly: boolean; // @DataMember - public passwordComplexity?: PasswordComplexityDto; + public allowAnyoneToSignUp: boolean; public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -7336,6 +7847,9 @@ export class TaxonomyDto implements IHasViewId // @DataMember public description?: string; + // @DataMember + public env?: string; + // @DataMember public termsMetaDataSchema?: DataSchemaDto; @@ -7385,6 +7899,9 @@ export class TaxonomyListProjection implements IHasViewId // @DataMember public dependencyRefs?: TaxonomyRef[]; + // @DataMember + public env?: string; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -7510,6 +8027,9 @@ export class TermDto // @DataMember public meta?: Object; + // @DataMember + public origin?: string; + public constructor(init?: Partial) { (Object as any).assign(this, init); } } @@ -8501,6 +9021,9 @@ export class EmailCampaignBatchNotificationDto extends CampaignBatchNotification // @DataMember public content?: EmailMessageContentDto; + // @DataMember + public transactionalKind?: string; + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -9121,6 +9644,21 @@ export class PushDeviceListProjection public constructor(init?: Partial) { (Object as any).assign(this, init); } } +// @DataContract +export class TeamPushDeviceListProjection extends PushDeviceListProjection +{ + // @DataMember + public ownerKind: string; + + // @DataMember + public ownerName?: string; + + // @DataMember + public ownerEmail?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + // @DataContract export class PushAudienceCountDto { @@ -9229,6 +9767,22 @@ export class PushCampaignBatchNotificationDto extends CampaignBatchNotificationD public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class InAppNotificationDto +{ + public id: string; + public projectId: string; + public userId: string; + public channel: string; + public eventName: string; + public payloadJson?: string; + public isRead: boolean; + public seenAtUtc?: string; + public readAtUtc?: string; + public createdAtUtc: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + export class PaymentsWebhookLogEntry { public integrationId: string; @@ -9327,6 +9881,68 @@ export class AgentOnboardingSnippet public constructor(init?: Partial) { (Object as any).assign(this, init); } } +export class AiProjectContextCallerWireDto +{ + public kind: string; + public name?: string; + public accountId?: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class AiProjectContextIntegrationWireDto +{ + public id: string; + public name?: string; + public kind?: string; + public enabled?: boolean; + public defaultIn: string[] = []; + public env?: string; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class AiProjectContextModuleWireDto +{ + public name: string; + public integrationsReadable?: boolean; + public integrations?: AiProjectContextIntegrationWireDto[]; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class AiProjectContextProjectWireDto +{ + public id: string; + public name: string; + public uniqueName?: string; + public access: string; + public description?: string; + public defaultLanguage?: string; + public languages: string[] = []; + public environments?: string[]; + public primaryRegion?: string; + public additionalRegions?: string[]; + public corsOrigins?: string[]; + public apiHost?: string; + public adminUrl?: string; + public marketingUrl?: string; + public adminPortalEnabled?: boolean; + public modules?: AiProjectContextModuleWireDto[]; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + +export class AiProjectContextWireDto +{ + public version: string; + public caller: AiProjectContextCallerWireDto; + public projects: AiProjectContextProjectWireDto[] = []; + public hints: string[] = []; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } +} + export class AiToolManifestParameter { public name: string; @@ -9891,6 +10507,12 @@ export class SchedulerTaskListProjection implements IHasViewId // @DataMember public lastFailedAtUnix?: number; + // @DataMember + public endsAtUnix?: number; + + // @DataMember + public hasEnded: boolean; + // @DataMember public viewId: string; @@ -10703,6 +11325,15 @@ export class PublicLegalDocumentDto public constructor(init?: Partial) { (Object as any).assign(this, init); } } +// @DataContract +export class GetTriggerDefinitionResponse extends ResponseBase +{ + // @DataMember + public trigger?: SaveTriggerRequest; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + // @DataContract export class GetTriggersNeedingAttentionResponse extends ResponseBase { @@ -10712,6 +11343,21 @@ export class GetTriggersNeedingAttentionResponse extends ResponseBase public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +// @DataContract +export class TestTriggerPreExecuteCodeResponse extends ResponseBase +{ + // @DataMember + public outcome: string; + + // @DataMember + public triggerRuns: boolean; + + // @DataMember + public problems: TriggerActivationTestProblem[] = []; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + export class GetAccountProfileResponse extends ResponseBase { public item?: AccountOwnerDto; @@ -11054,6 +11700,20 @@ export class RotateAiServiceUserKeyResponse extends ResponseBase public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class ImportUsersResponse extends ResponseBase +{ + public result?: UsersImportDto; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class RepairLoginProjectIdsResponse extends ResponseBase +{ + public result?: LoginProjectRepairDto; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + export class IssueServiceUserApiKeyResponse { public id: number; @@ -12104,6 +12764,7 @@ export class GetPushDeviceResponse extends ResponseBase export class GetPushDevicesResponse extends ResponseBase { public list?: PaginatedResponse; + public teamDevices: TeamPushDeviceListProjection[] = []; public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -12174,6 +12835,32 @@ export class GetPushCampaignMessagesResponse extends ResponseBase public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class GetNotificationInboxResponse extends ResponseBase +{ + public list?: PaginatedResponse; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class GetUnreadCountResponse extends ResponseBase +{ + public count: number; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class MarkNotificationReadResponse extends ResponseBase +{ + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + +export class MarkAllNotificationsReadResponse extends ResponseBase +{ + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + export class GetPaymentsWebhookLogResponse extends ResponseBase { public list?: IReadOnlyList; @@ -12290,6 +12977,16 @@ export class GetAgentOnboardingResponse extends ResponseBase public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } +export class GetAiContextResponse extends ResponseBase +{ + public version?: string; + public unchanged: boolean; + public context?: AiProjectContextWireDto; + public markdown?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } +} + export class GetAiToolsResponse extends ResponseBase { public tools?: AiToolManifestItem[]; @@ -12377,6 +13074,7 @@ export class ValidateSchemaResponse extends ResponseBase public valid: boolean; public issues?: ScaffoldIssue[]; public collections?: string[]; + public warnings?: ScaffoldIssue[]; public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } } @@ -13312,6 +14010,14 @@ export class InternalsTypeGen public typegen_53_StripePaymentIntegrationRequest?: StripePaymentIntegrationRequest; public typegen_54_AppleInAppPaymentIntegrationRequest?: AppleInAppPaymentIntegrationRequest; public typegen_55_GoogleInAppPaymentIntegrationRequest?: GoogleInAppPaymentIntegrationRequest; + public typegen_285_MontonioPaymentIntegrationRequest?: MontonioPaymentIntegrationRequest; + public typegen_287_ShopifyPaymentIntegrationRequest?: ShopifyPaymentIntegrationRequest; + public typegen_288_WooCommercePaymentIntegrationRequest?: WooCommercePaymentIntegrationRequest; + public typegen_289_MagentoPaymentIntegrationRequest?: MagentoPaymentIntegrationRequest; + public typegen_290_BraintreePaymentIntegrationRequest?: BraintreePaymentIntegrationRequest; + public typegen_291_AuthorizeNetPaymentIntegrationRequest?: AuthorizeNetPaymentIntegrationRequest; + public typegen_292_CheckOutComPaymentIntegrationRequest?: CheckOutComPaymentIntegrationRequest; + public typegen_293_WorldpayPaymentIntegrationRequest?: WorldpayPaymentIntegrationRequest; public typegen_56_EdgeWebPushIntegrationRequest?: EdgeWebPushIntegrationRequest; public typegen_57_ChromePluginPushIntegrationRequest?: ChromePluginPushIntegrationRequest; public typegen_58_SafariPushIntegrationRequest?: SafariPushIntegrationRequest; @@ -13395,6 +14101,8 @@ export class InternalsTypeGen public typegen_188_AuthorizeNetPaymentIntegrationDto?: AuthorizeNetPaymentIntegrationDto; public typegen_189_CheckOutComPaymentIntegrationDto?: CheckOutComPaymentIntegrationDto; public typegen_190_WorldpayPaymentIntegrationDto?: WorldpayPaymentIntegrationDto; + public typegen_286_MontonioPaymentIntegrationDto?: MontonioPaymentIntegrationDto; + public typegen_294_PaymentOrderEventDto?: PaymentOrderEventDto; public typegen_128_AppleSignInMembershipIntegrationDto?: AppleSignInMembershipIntegrationDto; public typegen_129_GitHubMembershipIntegrationDto?: GitHubMembershipIntegrationDto; public typegen_130_GoogleMembershipIntegrationDto?: GoogleMembershipIntegrationDto; @@ -13504,23 +14212,6 @@ export class InternalsTypeGen public typegen_243_ActionPendingEntryWireDto?: ActionPendingEntryWireDto; public typegen_244_NoticeEntryWireDto?: NoticeEntryWireDto; public typegen_245_ConversationSnapshotEntryWireDto?: ConversationSnapshotEntryWireDto; - public typegen_252_StringFieldDto?: StringFieldDto; - public typegen_253_DecimalFieldDto?: DecimalFieldDto; - public typegen_254_CurrencyFieldDto?: CurrencyFieldDto; - public typegen_255_BooleanFieldDto?: BooleanFieldDto; - public typegen_256_DateFieldDto?: DateFieldDto; - public typegen_257_IntegerFieldDto?: IntegerFieldDto; - public typegen_258_GeolocationFieldDto?: GeolocationFieldDto; - public typegen_259_TagsFieldDto?: TagsFieldDto; - public typegen_260_FileFieldDto?: FileFieldDto; - public typegen_261_TaxonomySelectionFieldDto?: TaxonomySelectionFieldDto; - public typegen_262_CollectionSelectionFieldDto?: CollectionSelectionFieldDto; - public typegen_263_UserSelectionFieldDto?: UserSelectionFieldDto; - public typegen_264_RoleSelectionFieldDto?: RoleSelectionFieldDto; - public typegen_265_EnumSelectionFieldDto?: EnumSelectionFieldDto; - public typegen_266_ObjectFieldDto?: ObjectFieldDto; - public typegen_267_ArrayFieldDto?: ArrayFieldDto; - public typegen_268_JsonFieldDto?: JsonFieldDto; public typegen_269_FunctionRefDto?: FunctionRefDto; public typegen_270_CodeFunctionEventDto?: CodeFunctionEventDto; public typegen_271_CodeFunctionContextDto?: CodeFunctionContextDto; @@ -13544,6 +14235,32 @@ export class InternalsTypeGen public createResponse() {} } +export class SharedTypeGen +{ + public typegen_StringFieldDto?: StringFieldDto; + public typegen_DecimalFieldDto?: DecimalFieldDto; + public typegen_CurrencyFieldDto?: CurrencyFieldDto; + public typegen_BooleanFieldDto?: BooleanFieldDto; + public typegen_DateFieldDto?: DateFieldDto; + public typegen_IntegerFieldDto?: IntegerFieldDto; + public typegen_GeolocationFieldDto?: GeolocationFieldDto; + public typegen_TagsFieldDto?: TagsFieldDto; + public typegen_FileFieldDto?: FileFieldDto; + public typegen_TaxonomySelectionFieldDto?: TaxonomySelectionFieldDto; + public typegen_CollectionSelectionFieldDto?: CollectionSelectionFieldDto; + public typegen_UserSelectionFieldDto?: UserSelectionFieldDto; + public typegen_RoleSelectionFieldDto?: RoleSelectionFieldDto; + public typegen_EnumSelectionFieldDto?: EnumSelectionFieldDto; + public typegen_ObjectFieldDto?: ObjectFieldDto; + public typegen_ArrayFieldDto?: ArrayFieldDto; + public typegen_JsonFieldDto?: JsonFieldDto; + + public constructor(init?: Partial) { (Object as any).assign(this, init); } + public getTypeName() { return 'SharedTypeGen'; } + public getMethod() { return 'POST'; } + public createResponse() {} +} + // @Route("/{version}/echo", "GET") export class Echo extends RequestBase implements IReturn { @@ -13590,6 +14307,33 @@ export class GetPublicProjectLegal extends RequestBase implements IReturn +{ + /** @description The trigger id (trg_…). */ + // @DataMember + // @ApiMember(Description="The trigger id (trg_…).", IsRequired=true) + public id: string; + + /** @description Which module the trigger belongs to: Schema, Membership, Files, Payments or Ai. */ + // @DataMember + // @ApiMember(Description="Which module the trigger belongs to: Schema, Membership, Files, Payments or Ai.", IsRequired=true) + public triggerType: TriggerType; + + /** @description The collection (schema) id the trigger watches. Required for Schema triggers. */ + // @DataMember + // @ApiMember(Description="The collection (schema) id the trigger watches. Required for Schema triggers.") + public schemaId?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetTriggerDefinition'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetTriggerDefinitionResponse(); } +} + /** @description Get triggers that need attention */ // @Route("/{version}/triggers/attention", "GET") // @Api(Description="Get triggers that need attention") @@ -13607,6 +14351,48 @@ export class GetTriggersNeedingAttention extends CodeMashRequestBase implements public createResponse() { return new GetTriggersNeedingAttentionResponse(); } } +/** @description Test a trigger's pre-action code against a sample record */ +// @Route("/{version}/triggers/pre-execute-code/test", "POST") +// @Api(Description="Test a trigger's pre-action code against a sample record") +// @DataContract +export class TestTriggerPreExecuteCode extends CodeMashRequestBase implements IReturn +{ + /** @description The code to test, as saved in preExecuteCode: C# statements ending in 'return true;' or 'return false;', e.g. 'return New.status == "published";'. */ + // @DataMember + // @ApiMember(Description="The code to test, as saved in preExecuteCode: C# statements ending in 'return true;' or 'return false;', e.g. 'return New.status == \"published\";'.", IsRequired=true) + public code: string; + + /** @description Which kind of trigger the code is for: Schema, Membership, Files, Payments or Ai. */ + // @DataMember + // @ApiMember(Description="Which kind of trigger the code is for: Schema, Membership, Files, Payments or Ai.", IsRequired=true) + public triggerType: TriggerType; + + /** @description The sample record AFTER the change (the code's New), as a JSON object. Omit = empty (a delete). */ + // @DataMember + // @ApiMember(Description="The sample record AFTER the change (the code's New), as a JSON object. Omit = empty (a delete).") + public newRecord?: string; + + /** @description The sample record BEFORE the change (the code's Old), as a JSON object. Omit = empty (an insert). */ + // @DataMember + // @ApiMember(Description="The sample record BEFORE the change (the code's Old), as a JSON object. Omit = empty (an insert).") + public oldRecord?: string; + + /** @description What the code sees as Event.Kind: Inserted, Updated, Deleted or Other. Omit = Updated when both records are given, Inserted when only newRecord, Deleted when only oldRecord. */ + // @DataMember + // @ApiMember(Description="What the code sees as Event.Kind: Inserted, Updated, Deleted or Other. Omit = Updated when both records are given, Inserted when only newRecord, Deleted when only oldRecord.") + public eventKind?: string; + + /** @description What the code sees as Event.Name, e.g. database.record.updated. Optional. */ + // @DataMember + // @ApiMember(Description="What the code sees as Event.Name, e.g. database.record.updated. Optional.") + public eventName?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'TestTriggerPreExecuteCode'; } + public getMethod() { return 'POST'; } + public createResponse() { return new TestTriggerPreExecuteCodeResponse(); } +} + // @Route("/{version}/account/profile", "GET") export class GetAccountProfile extends RequestBase implements IReturn { @@ -14141,8 +14927,8 @@ export class GetAdminPortalStructure extends CodeMashRequestBase implements IRet // @Api(Description="Updates the project's admin-portal URL override") export class UpdateProjectAdminUrl extends CodeMashRequestBase implements IReturn { - /** @description Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr_{id}.admin.{host} address. */ - // @ApiMember(Description="Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr_{id}.admin.{host} address.") + /** @description Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr-{project hex}.admin.{host} address. */ + // @ApiMember(Description="Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr-{project hex}.admin.{host} address.") public url?: string; public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } @@ -14400,8 +15186,8 @@ export class UpdateProjectAllowedOrigins extends CodeMashRequestBase implements // @ApiMember(Description="The complete new list of allowed origin URLs, e.g. [\"https://app.example.com\", \"https://example.com\"]. An entry with no scheme (e.g. \"example.com\") defaults to https. Whatever is not in this list stops being allowed.") public origins?: string[]; - /** @description Optional. true removes the project's own Admin Portal origin (pr_{projectId}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API. */ - // @ApiMember(Description="Optional. true removes the project's own Admin Portal origin (pr_{projectId}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API.") + /** @description Optional. true removes the project's own Admin Portal origin (pr-{project hex}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API. */ + // @ApiMember(Description="Optional. true removes the project's own Admin Portal origin (pr-{project hex}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API.") public removeAdminPortalOrigin?: boolean; public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } @@ -15192,6 +15978,23 @@ export class RevokeAiServiceUserKeyRequest extends RequestBase implements IRetur public createResponse() { return new EmptyResponse(); } } +// @Route("/{version}/account/ai/service-users/{Id}", "PUT") +export class UpdateAiServiceUserRequest extends RequestBase implements IReturn +{ + /** @description The service user id (aisu_…). */ + // @ApiMember(Description="The service user id (aisu_…).", IsRequired=true) + public id: string; + + /** @description The new name, unique in the account, e.g. "Claude Code on my laptop". */ + // @ApiMember(Description="The new name, unique in the account, e.g. \"Claude Code on my laptop\".", IsRequired=true) + public name: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'UpdateAiServiceUserRequest'; } + public getMethod() { return 'PUT'; } + public createResponse() { return new EmptyResponse(); } +} + // @Route("/{version}/account/ai/service-users/{Id}", "DELETE") export class DeleteAiServiceUserRequest extends RequestBase implements IReturn { @@ -15225,6 +16028,44 @@ export class EnableMembership extends CodeMashRequestBase implements IReturn +{ + /** @description True (default) = check every row and write nothing. False = write. */ + // @ApiMember(Description="True (default) = check every row and write nothing. False = write.") + public dryRun: boolean; + + /** @description True = do not add the project's default roles (as 'ignoreUserRegistersAsRole' on registration). */ + // @ApiMember(Description="True = do not add the project's default roles (as 'ignoreUserRegistersAsRole' on registration).") + public ignoreDefaultRoles: boolean; + + /** @description The users to import, 1 to 1000 per request. */ + // @ApiMember(Description="The users to import, 1 to 1000 per request.", IsRequired=true) + public users: ImportUserRowDto[] = []; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'ImportUsersRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new ImportUsersResponse(); } +} + +/** @description Repair project logins stored without a project id */ +// @Route("/{version}/membership/users/repair-logins", "POST") +// @Api(Description="Repair project logins stored without a project id") +export class RepairLoginProjectIdsRequest extends CodeMashRequestBase implements IReturn +{ + /** @description True (default) = only count what would change. False = write. */ + // @ApiMember(Description="True (default) = only count what would change. False = write.") + public dryRun: boolean; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'RepairLoginProjectIdsRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new RepairLoginProjectIdsResponse(); } +} + /** @description Membership */ // @Route("/{version}/membership/users/{Id}/api-keys", "POST") // @Api(Description="Membership") @@ -15704,11 +16545,26 @@ export class GetAuthorizationSettings extends CodeMashRequestBase implements IRe // @Api(Description="Updates the project's membership authorization settings.") export class UpdateAuthorizationSettings extends CodeMashRequestBase implements IReturn { + /** @description Single-setting change (dashboard tabs), e.g. 'DefaultRegisterRole' with userRegistersAsRole, or 'PasswordComplexity'. Unknown values are refused. Leave empty to change defaultRoles / allowedRegistrationRoles / allowGuestUsers / guestCleanupPeriodDays — only the fields you send change. */ + // @ApiMember(Description="Single-setting change (dashboard tabs), e.g. 'DefaultRegisterRole' with userRegistersAsRole, or 'PasswordComplexity'. Unknown values are refused. Leave empty to change defaultRoles / allowedRegistrationRoles / allowGuestUsers / guestCleanupPeriodDays — only the fields you send change.") public setting?: string; + + /** @description Role names given to a user who registers without naming roles. Omit = keep; [] = none. */ + // @ApiMember(Description="Role names given to a user who registers without naming roles. Omit = keep; [] = none.") public defaultRoles?: string[]; + + /** @description Role names a user may pick when registering. Omit = keep; [] = none. */ + // @ApiMember(Description="Role names a user may pick when registering. Omit = keep; [] = none.") public allowedRegistrationRoles?: string[]; - public allowGuestUsers: boolean; + + /** @description Whether guest (anonymous) users may be created. Omit = keep. When sent, guestCleanupPeriodDays is taken with it (null = never clean up). */ + // @ApiMember(Description="Whether guest (anonymous) users may be created. Omit = keep. When sent, guestCleanupPeriodDays is taken with it (null = never clean up).") + public allowGuestUsers?: boolean; + + /** @description Days after which inactive guests are removed; null or 0 = never. Omit both guest fields = keep. */ + // @ApiMember(Description="Days after which inactive guests are removed; null or 0 = never. Omit both guest fields = keep.") public guestCleanupPeriodDays?: number; + public userRegistersAsRole?: string; public guestRegistersAsRole?: string; public allowedRegisterRoles?: string[]; @@ -15722,6 +16578,18 @@ export class UpdateAuthorizationSettings extends CodeMashRequestBase implements public emailVerificationExpiration?: number; public deactivationExpiration?: number; public defaultSubscribeToNews: boolean; + /** @description "Email registration": the public register/email route accepts sign-ups. Omit = keep. */ + // @ApiMember(Description="\"Email registration\": the public register/email route accepts sign-ups. Omit = keep.") + public allowEmailRegistration?: boolean; + + /** @description "Invite-only": public sign-up (email and username) is refused; only invitations create users. Omit = keep. */ + // @ApiMember(Description="\"Invite-only\": public sign-up (email and username) is refused; only invitations create users. Omit = keep.") + public inviteOnly?: boolean; + + /** @description "Allow anyone to sign up": grants (true) / revokes (false) membership:register on the project's Guest role. Omit = keep. */ + // @ApiMember(Description="\"Allow anyone to sign up\": grants (true) / revokes (false) membership:register on the project's Guest role. Omit = keep.") + public allowAnyoneToSignUp?: boolean; + public minLength: number; public maxLength?: number; public minNumbers?: number; @@ -16049,9 +16917,9 @@ export class SaveDatabaseTaxonomyRequest extends CodeMashRequestBase implements // @DataContract export class DeleteDatabaseTaxonomyTermRequest extends CodeMashRequestBase implements IReturn { - /** @description Taxonomy id that owns the term, from get_database_taxonomies. */ + /** @description Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title). */ // @DataMember - // @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) public taxonomyId: string; /** @description Term id to delete, from get_database_taxonomy_term_tree. */ @@ -16076,9 +16944,9 @@ export class DeleteDatabaseTaxonomyTermRequest extends CodeMashRequestBase imple // @DataContract export class DeleteManyDatabaseTaxonomyTermsRequest extends CodeMashRequestBase implements IReturn { - /** @description Taxonomy id whose terms to delete, from get_database_taxonomies. */ + /** @description Taxonomy id whose terms to delete, from get_database_taxonomies — or the taxonomy name (slug or title). */ // @DataMember - // @ApiMember(Description="Taxonomy id whose terms to delete, from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy id whose terms to delete, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) public taxonomyId: string; /** @description Optional database integration id. When omitted, the project's default database integration is used. */ @@ -16108,9 +16976,9 @@ export class GetDatabaseTaxonomyTermRequest extends CodeMashRequestBase implemen // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; - /** @description Taxonomy id from get_database_taxonomies. */ + /** @description Taxonomy id from get_database_taxonomies — or the taxonomy name (slug or title). */ // @DataMember - // @ApiMember(Description="Taxonomy id from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy id from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) public taxonomyId: string; /** @description Term id from get_database_taxonomy_term_tree. */ @@ -16140,9 +17008,9 @@ export class GetDatabaseMergedTermTreeRequest extends CodeMashRequestBase implem // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; - /** @description Root taxonomy slug/name (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them. */ + /** @description Root taxonomy slug/name or id, txn_… (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them. */ // @DataMember - // @ApiMember(Description="Root taxonomy slug/name (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them.", IsRequired=true) + // @ApiMember(Description="Root taxonomy slug/name or id, txn_… (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them.", IsRequired=true) public taxonomyName: string; /** @description Optional database integration id. When omitted, the project's default database integration is used. */ @@ -16167,9 +17035,9 @@ export class GetDatabaseTaxonomyTermTreeRequest extends CodeMashRequestBase impl // @ApiMember(Description="Set true to keep name / description as stored even when Accept-Language is sent (editors). The full translations are always in names / descriptions.") public allLanguages: boolean; - /** @description Taxonomy slug/name to fetch the term tree for, from get_database_taxonomies. */ + /** @description Taxonomy slug/name (or its id, txn_…) to fetch the term tree for, from get_database_taxonomies. */ // @DataMember - // @ApiMember(Description="Taxonomy slug/name to fetch the term tree for, from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy slug/name (or its id, txn_…) to fetch the term tree for, from get_database_taxonomies.", IsRequired=true) public taxonomyName: string; /** @description Optional term id to root the returned tree at a sub-tree instead of the whole taxonomy. */ @@ -16199,9 +17067,9 @@ export class GetDatabaseTaxonomyTermTreeRequest extends CodeMashRequestBase impl // @DataContract export class SaveDatabaseTaxonomyTermRequest extends CodeMashRequestBase implements IReturn { - /** @description Taxonomy id to insert the term into, from get_database_taxonomies. */ + /** @description Taxonomy id to insert the term into, from get_database_taxonomies — or the taxonomy name (slug or title). */ // @DataMember - // @ApiMember(Description="Taxonomy id to insert the term into, from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy id to insert the term into, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) public taxonomyId: string; /** @description Optional database integration id. When omitted, the project's default database integration is used. */ @@ -16226,9 +17094,9 @@ export class SaveDatabaseTaxonomyTermRequest extends CodeMashRequestBase impleme // @DataContract export class UpdateDatabaseTaxonomyTermRequest extends CodeMashRequestBase implements IReturn { - /** @description Taxonomy id that owns the term, from get_database_taxonomies. */ + /** @description Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title). */ // @DataMember - // @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies.", IsRequired=true) + // @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) public taxonomyId: string; /** @description Term id to update, from get_database_taxonomy_term_tree. */ @@ -19831,9 +20699,9 @@ export class TestPushIntegration extends CodeMashRequestBase implements IReturn< // @ApiMember(Description="The push integration id to test. Get it from get_push_integrations.", IsRequired=true) public integrationId: string; - /** @description The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Fake integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily. */ + /** @description The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Sandbox integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily. */ // @DataMember - // @ApiMember(Description="The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Fake integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily.") + // @ApiMember(Description="The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Sandbox integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily.") public testToken?: string; /** @description The delivery family of TestToken: ios, android, chrome (any browser web push) or safari. Requires TestToken. */ @@ -20201,6 +21069,49 @@ export class GetPushCampaignMessagesRequest extends CodeMashListPaginationReques public createResponse() { return new GetPushCampaignMessagesResponse(); } } +// @Route("/{version}/notifications/inbox", "GET") +export class GetNotificationInboxRequest extends CodeMashListPaginationRequestBase implements IReturn +{ + public unreadOnly: boolean; + public channel?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetNotificationInboxRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetNotificationInboxResponse(); } +} + +// @Route("/{version}/notifications/inbox/unread-count", "GET") +export class GetUnreadCountRequest extends CodeMashRequestBase implements IReturn +{ + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetUnreadCountRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetUnreadCountResponse(); } +} + +// @Route("/{version}/notifications/inbox/{notificationId}/read", "POST") +export class MarkNotificationReadRequest extends CodeMashRequestBase implements IReturn +{ + public notificationId: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'MarkNotificationReadRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new MarkNotificationReadResponse(); } +} + +// @Route("/{version}/notifications/inbox/read-all", "POST") +export class MarkAllNotificationsReadRequest extends CodeMashRequestBase implements IReturn +{ + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'MarkAllNotificationsReadRequest'; } + public getMethod() { return 'POST'; } + public createResponse() { return new MarkAllNotificationsReadResponse(); } +} + /** @description Disable payments service */ // @Route("/{version}/payments/disable", "PUT") // @Api(Description="Disable payments service") @@ -20689,6 +21600,21 @@ export class GetAgentOnboardingRequest extends RequestBase implements IReturn +{ + public projectId?: string; + public format?: string; + public knownVersion?: string; + + public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } + public getTypeName() { return 'GetAiContextRequest'; } + public getMethod() { return 'GET'; } + public createResponse() { return new GetAiContextResponse(); } +} + /** @description Lists the AI tools this host exposes (external-agent bridge). */ // @Route("/{version}/account/ai/tools", "GET") // @Api(Description="Lists the AI tools this host exposes (external-agent bridge).") @@ -21181,7 +22107,7 @@ export class DeleteAiProjectTrigger extends DeleteTrigger implements IReturn +export class AuthDeviceStartRequest extends RequestBase implements IReturn, INoSessionCookies { /** @description Who asks, shown on the dashboard, e.g. "norbix-cli". 1–80 printable characters. */ // @ApiMember(Description="Who asks, shown on the dashboard, e.g. \"norbix-cli\". 1–80 printable characters.", IsRequired=true) @@ -21204,7 +22130,7 @@ export class AuthDeviceStartRequest extends RequestBase implements IReturn +export class AuthDeviceTokenRequest extends RequestBase implements IReturn, INoSessionCookies { /** @description The deviceCode from POST /auth/device/start. */ // @ApiMember(Description="The deviceCode from POST /auth/device/start.", IsRequired=true) @@ -21262,7 +22188,7 @@ export class AuthDeviceConsentDecisionRequest extends RequestBase implements IRe // @Route("/.well-known/oauth-protected-resource", "GET") // @Route("/.well-known/oauth-protected-resource/{Path*}", "GET") // @Api(Description="OAuth protected-resource metadata (RFC 9728) for the Hub MCP endpoint.") -export class OAuthProtectedResourceMetadataRequest implements IReturn +export class OAuthProtectedResourceMetadataRequest implements IReturn, INoSessionCookies { public path?: string; @@ -21276,7 +22202,7 @@ export class OAuthProtectedResourceMetadataRequest implements IReturn // @Route("/.well-known/oauth-authorization-server", "GET") // @Route("/.well-known/oauth-authorization-server/{Path*}", "GET") // @Api(Description="OAuth authorization-server metadata (RFC 8414).") -export class OAuthAuthorizationServerMetadataRequest implements IReturn +export class OAuthAuthorizationServerMetadataRequest implements IReturn, INoSessionCookies { public path?: string; @@ -21289,7 +22215,7 @@ export class OAuthAuthorizationServerMetadataRequest implements IReturn /** @description Registers an MCP client for OAuth (RFC 7591). Public clients only: PKCE, no secret. */ // @Route("/{version}/oauth/register", "POST") // @Api(Description="Registers an MCP client for OAuth (RFC 7591). Public clients only: PKCE, no secret.") -export class OAuthRegisterRequest implements IReturn +export class OAuthRegisterRequest implements IReturn, INoSessionCookies { public version?: string; public requestStream: string; @@ -21303,7 +22229,7 @@ export class OAuthRegisterRequest implements IReturn /** @description OAuth authorization endpoint: checks the request and redirects to the dashboard consent screen. */ // @Route("/{version}/oauth/authorize", "GET") // @Api(Description="OAuth authorization endpoint: checks the request and redirects to the dashboard consent screen.") -export class OAuthAuthorizeRequest implements IReturn +export class OAuthAuthorizeRequest implements IReturn, INoSessionCookies { public version?: string; @@ -21418,7 +22344,7 @@ export class OAuthConsentDecisionRequest extends RequestBase implements IReturn< /** @description OAuth token endpoint: authorization code (PKCE S256) or refresh token → access token. */ // @Route("/{version}/oauth/token", "POST") // @Api(Description="OAuth token endpoint: authorization code (PKCE S256) or refresh token → access token.") -export class OAuthTokenRequest implements IReturn +export class OAuthTokenRequest implements IReturn, INoSessionCookies { public version?: string; @@ -21431,7 +22357,7 @@ export class OAuthTokenRequest implements IReturn /** @description OAuth token revocation (RFC 7009): revokes the grant behind a refresh or access token. */ // @Route("/{version}/oauth/revoke", "POST") // @Api(Description="OAuth token revocation (RFC 7009): revokes the grant behind a refresh or access token.") -export class OAuthRevokeRequest implements IReturn +export class OAuthRevokeRequest implements IReturn, INoSessionCookies { public version?: string; @@ -21951,6 +22877,9 @@ export class SaveSchedulerTaskRequest extends CodeMashRequestBase implements IRe // @DataMember public stopOnError: boolean; + // @DataMember + public endsAtUnix?: number; + // @DataMember public task: SchedulerTaskRequest; @@ -22045,8 +22974,8 @@ export class DeleteContact extends CodeMashRequestBase implements IReturn { - /** @description The contact id (ct_…) to fetch. Get it from get_all_contacts. */ - // @ApiMember(Description="The contact id (ct_…) to fetch. Get it from get_all_contacts.", IsRequired=true) + /** @description The contact id (ct_…) to fetch, or a login id (usr_…) — then the contact that owns that login is returned. Get it from get_all_contacts. */ + // @ApiMember(Description="The contact id (ct_…) to fetch, or a login id (usr_…) — then the contact that owns that login is returned. Get it from get_all_contacts.", IsRequired=true) public contactId: string; public constructor(init?: Partial) { super(init); (Object as any).assign(this, init); } @@ -22068,6 +22997,30 @@ export class GetAllContacts extends CodeMashRequestBase implements IReturn) { super(init); (Object as any).assign(this, init); } public getTypeName() { return 'GetAllContacts'; } public getMethod() { return 'GET'; } diff --git a/references/hub_dtos.py b/references/hub_dtos.py index a046e84..a8c0281 100644 --- a/references/hub_dtos.py +++ b/references/hub_dtos.py @@ -1,5 +1,5 @@ """ Options: -Date: 2026-10-14 08:01:43 +Date: 2026-10-19 11:26:14 Version: 10.20 Tip: To override a DTO option, remove "#" prefix before updating BaseUrl: http://localhost:5001 @@ -279,6 +279,9 @@ class SchemaTriggerType(str, Enum): ON_INSERTED = 'OnInserted' ON_DELETED = 'OnDeleted' ON_UPDATED = 'OnUpdated' + ON_INSERTED_MANY = 'OnInsertedMany' + ON_UPDATED_MANY = 'OnUpdatedMany' + ON_DELETED_MANY = 'OnDeletedMany' @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -307,6 +310,7 @@ class PaymentTriggerType(str, Enum): ON_ORDER_CREATED = 'OnOrderCreated' ON_ORDER_PAID = 'OnOrderPaid' ON_WEBHOOK_CALL_RECEIVED = 'OnWebhookCallReceived' + ON_ORDER_PAYMENT_CHANGED = 'OnOrderPaymentChanged' @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -779,6 +783,7 @@ class PaymentGatewayPlatform(str, Enum): CHECK_OUT_COM = 'CheckOutCom' MOLLIE = 'Mollie' WORLDPAY = 'Worldpay' + MONTONIO = 'Montonio' @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -879,6 +884,80 @@ class GoogleInAppPaymentIntegrationRequest(PaymentIntegrationRequest): webhook_package_name: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MontonioPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + access_key: Optional[str] = None + secret_key: Optional[str] = None + is_sandbox: bool = False + locale: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ShopifyPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + shop_domain: Optional[str] = None + webhook_secret: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class WooCommercePaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + store_url: Optional[str] = None + webhook_secret: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MagentoPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + store_url: Optional[str] = None + webhook_secret: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class BraintreePaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + merchant_id: Optional[str] = None + environment: Optional[str] = None + private_key: Optional[str] = None + webhook_secret: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AuthorizeNetPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + merchant_login_id: Optional[str] = None + environment: Optional[str] = None + transaction_key: Optional[str] = None + webhook_signature_key: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CheckOutComPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + merchant_account: Optional[str] = None + environment: Optional[str] = None + secret_key: Optional[str] = None + webhook_secret: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class WorldpayPaymentIntegrationRequest(PaymentIntegrationRequest): + provider: Optional[PaymentGatewayPlatform] = None + merchant_code: Optional[str] = None + environment: Optional[str] = None + api_key: Optional[str] = None + webhook_secret: Optional[str] = None + + class PushProvider(str, Enum): APPLE_APNS = 'AppleApns' SAFARI_WEB = 'SafariWeb' @@ -1718,6 +1797,7 @@ class EmailToCollectionRecordsDeliverySettingsDto(EmailCampaignDeliverySettingsD field_type: Optional[CollectionEmailCampaignRecipientField] = None role_names: Optional[List[str]] = None languages: Optional[List[str]] = None + record_ids: Optional[List[str]] = None class PushDeviceDeliveryFamily(str, Enum): @@ -1757,6 +1837,7 @@ class PushToCollectionRecordsDeliverySettingsDto(PushCampaignDeliverySettingsDto schema_name: Optional[str] = None role_names: Optional[List[str]] = None languages: Optional[List[str]] = None + record_ids: Optional[List[str]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -1799,6 +1880,7 @@ class SmsToCollectionRecordsDeliverySettingsDto(SmsCampaignDeliverySettingsDto): schema_name: Optional[str] = None role_names: Optional[List[str]] = None languages: Optional[List[str]] = None + record_ids: Optional[List[str]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -2092,6 +2174,89 @@ class WorldpayPaymentIntegrationDto(PaymentsIntegrationDto): webhook_secret: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MontonioPaymentIntegrationDto(PaymentsIntegrationDto): + access_key: Optional[str] = None + is_sandbox: bool = False + locale: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderLineDto: + sku: Optional[str] = None + title: Optional[str] = None + quantity: int = 0 + unit_amount_minor: int = 0 + amount_minor: int = 0 + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderCheckoutDto: + attempt: int = 0 + integration_id: Optional[str] = None + provider: Optional[str] = None + provider_order_id: Optional[str] = None + provider_reference: Optional[str] = None + payment_url: Optional[str] = None + method: Optional[str] = None + started_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + expires_at_utc: datetime.datetime = datetime.datetime(1, 1, 1) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderDto: + id: Optional[str] = None + env: Optional[str] = None + buyer_user_id: Optional[str] = None + merchant_reference: Optional[str] = None + currency: Optional[str] = None + price_version: Optional[str] = None + lines: List[PaymentOrderLineDto] = field(default_factory=list) + total_minor: int = 0 + metadata: Dict[str, str] = field(default_factory=dict) + status: Optional[str] = None + created_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + updated_on_utc: datetime.datetime = datetime.datetime(1, 1, 1) + checkouts: List[PaymentOrderCheckoutDto] = field(default_factory=list) + settled_minor: Optional[int] = None + refunded_minor: int = 0 + paid_on_utc: Optional[datetime.datetime] = None + provider_payment_id: Optional[str] = None + mismatches: List[str] = field(default_factory=list) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentEventDto: + integration_id: Optional[str] = None + provider: Optional[str] = None + provider_event_id: Optional[str] = None + order_id: Optional[str] = None + event_name: Optional[str] = None + status: Optional[str] = None + amount_minor: Optional[int] = None + currency: Optional[str] = None + external_ids: Optional[Dict[str, str]] = None + occurred_on: Optional[datetime.datetime] = None + received_on: datetime.datetime = datetime.datetime(1, 1, 1) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PaymentOrderEventDto: + order_event_id: Optional[str] = None + event: Optional[str] = None + from_: Optional[str] = field(metadata=config(field_name='from'), default=None) + to: Optional[str] = None + reason: Optional[str] = None + order: Optional[PaymentOrderDto] = None + payment: Optional[PaymentEventDto] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class MembershipIntegrationDto(IntegrationDto): @@ -2598,6 +2763,8 @@ class SchedulerTaskDto: env: Optional[str] = None created_at_unix: Optional[int] = None updated_at_unix: Optional[int] = None + ends_at_unix: Optional[int] = None + has_ended: bool = False is_failing: bool = False last_failure_reason: Optional[str] = None last_failed_at_unix: Optional[int] = None @@ -3175,158 +3342,6 @@ class ConversationSnapshotEntryWireDto(AiChatEntryWireDto): covers_up_to_seq: int = 0 -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class JsonSchemaFieldDto: - field_name: Optional[str] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class StringFieldDto(JsonSchemaFieldDto): - format: Optional[str] = None - pattern: Optional[str] = None - min_length: Optional[int] = None - max_length: Optional[int] = None - translate_options: Optional[IReadOnlyDictionary[str, str]] = None - default: Optional[str] = None - unique: Optional[bool] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class DecimalFieldDto(JsonSchemaFieldDto): - minimum: Optional[Decimal] = None - maximum: Optional[Decimal] = None - multiple_of: Optional[Decimal] = None - default: Optional[Decimal] = None - unique: Optional[bool] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class CurrencyDefaultDto: - value: Decimal = decimal.Decimal(0) - currency: Optional[str] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class CurrencyFieldDto(JsonSchemaFieldDto): - allowed_currencies: Optional[IReadOnlyList[str]] = None - multiple_of: Optional[Decimal] = None - minimum: Optional[Decimal] = None - maximum: Optional[Decimal] = None - default: Optional[CurrencyDefaultDto] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class BooleanFieldDto(JsonSchemaFieldDto): - default: Optional[bool] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class DateFieldDto(JsonSchemaFieldDto): - minimum: Optional[int] = None - maximum: Optional[int] = None - default: Optional[int] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class IntegerFieldDto(JsonSchemaFieldDto): - minimum: Optional[int] = None - maximum: Optional[int] = None - default: Optional[int] = None - unique: Optional[bool] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class GeolocationFieldDto(JsonSchemaFieldDto): - allowed_types: Optional[IReadOnlyList[str]] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class TagsFieldDto(JsonSchemaFieldDto): - min_items: Optional[int] = None - max_items: Optional[int] = None - default: Optional[IReadOnlyList[str]] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class FileFieldDto(JsonSchemaFieldDto): - storages: Optional[IReadOnlyList[str]] = None - min_items: Optional[int] = None - max_items: Optional[int] = None - allowed_file_type: Optional[str] = None - max_size_mb: Optional[Decimal] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class TaxonomySelectionFieldDto(JsonSchemaFieldDto): - taxonomy_id: Optional[str] = None - multiple: bool = False - display_field: Optional[str] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class CollectionSelectionFieldDto(JsonSchemaFieldDto): - collection_id: Optional[str] = None - display_field: Optional[str] = None - multiple: bool = False - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class UserSelectionFieldDto(JsonSchemaFieldDto): - multiple: bool = False - display_field: Optional[str] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class RoleSelectionFieldDto(JsonSchemaFieldDto): - multiple: bool = False - display_field: Optional[str] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class EnumSelectionFieldDto(JsonSchemaFieldDto): - values: Optional[IReadOnlyList[str]] = None - multiple: bool = False - default: Optional[IReadOnlyList[str]] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class ObjectFieldDto(JsonSchemaFieldDto): - properties: Optional[IReadOnlyList[JsonSchemaFieldDto]] = None - required: Optional[IReadOnlyList[str]] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class ArrayFieldDto(JsonSchemaFieldDto): - items: Optional[JsonSchemaFieldDto] = None - min_items: Optional[int] = None - max_items: Optional[int] = None - unique_items: Optional[bool] = None - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class JsonFieldDto(JsonSchemaFieldDto): - max_bytes: Optional[int] = None - - class CodeFunctionSource(str, Enum): DATABASE = 'Database' MEMBERSHIP = 'Membership' @@ -3404,6 +3419,15 @@ class DocumentRefDto(ResourceRefDto): external_id: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class DatabaseRecordsBatchDto: + ids: List[str] = field(default_factory=list) + count: int = 0 + truncated: bool = False + documents: Optional[List[Dict[str, Object]]] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class DatabaseRecordChangeDto: @@ -3416,6 +3440,7 @@ class DatabaseRecordChangeDto: truncated: bool = False old_ref: Optional[DocumentRefDto] = None new_ref: Optional[DocumentRefDto] = None + records: Optional[DatabaseRecordsBatchDto] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -3440,6 +3465,7 @@ class PaymentFactDto: integration_id: Optional[str] = None provider: Optional[str] = None provider_event_id: Optional[str] = None + order_id: Optional[str] = None event_name: Optional[str] = None status: Optional[str] = None amount_minor: Optional[int] = None @@ -3466,68 +3492,221 @@ class ScheduledTaskInfoDto: @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class MarketplaceFunctionCallDto: - function_id: Optional[str] = None - function_key: Optional[str] = None - integration_id: Optional[str] = None - payload: Dict[str, Object] = field(default_factory=dict) +class MarketplaceFunctionCallDto: + function_id: Optional[str] = None + function_key: Optional[str] = None + integration_id: Optional[str] = None + payload: Dict[str, Object] = field(default_factory=dict) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CodeFunctionDataDto: + database: Optional[DatabaseRecordChangeDto] = None + user: Optional[UserChangeDto] = None + file: Optional[FileChangeDto] = None + payment: Optional[PaymentFactDto] = None + order: Optional[PaymentOrderEventDto] = None + ai: Optional[AiUsageEventDto] = None + task: Optional[ScheduledTaskInfoDto] = None + payload: Optional[Dict[str, Object]] = None + marketplace: Optional[MarketplaceFunctionCallDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CodeFunctionEventDto: + spec_version: Optional[str] = None + id: Optional[str] = None + event_id: Optional[str] = None + event: Optional[str] = None + source: Optional[CodeFunctionSource] = None + created_on: datetime.datetime = datetime.datetime(1, 1, 1) + context: Optional[CodeFunctionContextDto] = None + data: Optional[CodeFunctionDataDto] = None + config: Optional[Dict[str, Object]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class FakeCodeIntegrationDto(CodeIntegrationDto): + pass + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class FakeCodeIntegrationRequest(CodeIntegrationRequest): + provider: Optional[CodeProvider] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CodeFunctionSchedulerTaskRequest(SchedulerTaskRequest): + type: Optional[SchedulerTaskType] = None + function_ref: Optional[FunctionRefDto] = None + invocation_type: Optional[CodeInvocationType] = None + config: Optional[str] = None + mapped_tokens: Optional[List[TokenMappingDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarketplaceFunctionSchedulerTaskRequest(SchedulerTaskRequest): + type: Optional[SchedulerTaskType] = None + function_id: Optional[str] = None + payload: Optional[Dict[str, str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class JsonSchemaFieldDto: + field_name: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class StringFieldDto(JsonSchemaFieldDto): + format: Optional[str] = None + pattern: Optional[str] = None + min_length: Optional[int] = None + max_length: Optional[int] = None + translate_options: Optional[IReadOnlyDictionary[str, str]] = None + default: Optional[str] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class DecimalFieldDto(JsonSchemaFieldDto): + minimum: Optional[Decimal] = None + maximum: Optional[Decimal] = None + multiple_of: Optional[Decimal] = None + default: Optional[Decimal] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CurrencyDefaultDto: + value: Decimal = decimal.Decimal(0) + currency: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CurrencyFieldDto(JsonSchemaFieldDto): + allowed_currencies: Optional[IReadOnlyList[str]] = None + multiple_of: Optional[Decimal] = None + minimum: Optional[Decimal] = None + maximum: Optional[Decimal] = None + default: Optional[CurrencyDefaultDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class BooleanFieldDto(JsonSchemaFieldDto): + default: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class DateFieldDto(JsonSchemaFieldDto): + minimum: Optional[int] = None + maximum: Optional[int] = None + default: Optional[int] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class IntegerFieldDto(JsonSchemaFieldDto): + minimum: Optional[int] = None + maximum: Optional[int] = None + default: Optional[int] = None + unique: Optional[bool] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GeolocationFieldDto(JsonSchemaFieldDto): + allowed_types: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TagsFieldDto(JsonSchemaFieldDto): + min_items: Optional[int] = None + max_items: Optional[int] = None + default: Optional[IReadOnlyList[str]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class FileFieldDto(JsonSchemaFieldDto): + storages: Optional[IReadOnlyList[str]] = None + min_items: Optional[int] = None + max_items: Optional[int] = None + allowed_file_type: Optional[str] = None + max_size_mb: Optional[Decimal] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TaxonomySelectionFieldDto(JsonSchemaFieldDto): + taxonomy_id: Optional[str] = None + multiple: bool = False + display_field: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class CollectionSelectionFieldDto(JsonSchemaFieldDto): + collection_id: Optional[str] = None + display_field: Optional[str] = None + multiple: bool = False @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class CodeFunctionDataDto: - database: Optional[DatabaseRecordChangeDto] = None - user: Optional[UserChangeDto] = None - file: Optional[FileChangeDto] = None - payment: Optional[PaymentFactDto] = None - ai: Optional[AiUsageEventDto] = None - task: Optional[ScheduledTaskInfoDto] = None - payload: Optional[Dict[str, Object]] = None - marketplace: Optional[MarketplaceFunctionCallDto] = None +class UserSelectionFieldDto(JsonSchemaFieldDto): + multiple: bool = False + display_field: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class CodeFunctionEventDto: - spec_version: Optional[str] = None - id: Optional[str] = None - event_id: Optional[str] = None - event: Optional[str] = None - source: Optional[CodeFunctionSource] = None - created_on: datetime.datetime = datetime.datetime(1, 1, 1) - context: Optional[CodeFunctionContextDto] = None - data: Optional[CodeFunctionDataDto] = None - config: Optional[Dict[str, Object]] = None +class RoleSelectionFieldDto(JsonSchemaFieldDto): + multiple: bool = False + display_field: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class FakeCodeIntegrationDto(CodeIntegrationDto): - pass +class EnumSelectionFieldDto(JsonSchemaFieldDto): + values: Optional[IReadOnlyList[str]] = None + multiple: bool = False + default: Optional[IReadOnlyList[str]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class FakeCodeIntegrationRequest(CodeIntegrationRequest): - provider: Optional[CodeProvider] = None +class ObjectFieldDto(JsonSchemaFieldDto): + properties: Optional[IReadOnlyList[JsonSchemaFieldDto]] = None + required: Optional[IReadOnlyList[str]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class CodeFunctionSchedulerTaskRequest(SchedulerTaskRequest): - type: Optional[SchedulerTaskType] = None - function_ref: Optional[FunctionRefDto] = None - invocation_type: Optional[CodeInvocationType] = None - config: Optional[str] = None - mapped_tokens: Optional[List[TokenMappingDto]] = None +class ArrayFieldDto(JsonSchemaFieldDto): + items: Optional[JsonSchemaFieldDto] = None + min_items: Optional[int] = None + max_items: Optional[int] = None + unique_items: Optional[bool] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class MarketplaceFunctionSchedulerTaskRequest(SchedulerTaskRequest): - type: Optional[SchedulerTaskType] = None - function_id: Optional[str] = None - payload: Optional[Dict[str, str]] = None +class JsonFieldDto(JsonSchemaFieldDto): + max_bytes: Optional[int] = None class IVersionBasedRequest: @@ -3726,6 +3905,61 @@ class AiProjectRoleIdsDto: role_ids: List[str] = field(default_factory=list) +class Gender(str, Enum): + MALE = 'Male' + FEMALE = 'Female' + OTHER = 'Other' + + +class MarketingBlockReason(str, Enum): + UNSPECIFIED = 'Unspecified' + UNSUBSCRIBED = 'Unsubscribed' + COMPLAINT = 'Complaint' + HARD_BOUNCE = 'HardBounce' + INVALID_EMAIL = 'InvalidEmail' + ADMIN_BLOCK = 'AdminBlock' + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class UserGeneralInfoDto: + phone: Optional[str] = None + primary_email: Optional[str] = None + display_name: Optional[str] = None + first_name: Optional[str] = None + last_name: Optional[str] = None + full_name: Optional[str] = None + address_line1: Optional[str] = None + address_line2: Optional[str] = None + country: Optional[str] = None + city: Optional[str] = None + state: Optional[str] = None + postal_code: Optional[str] = None + company: Optional[str] = None + gender: Optional[Gender] = None + birth_date: Optional[int] = None + time_zone: Optional[str] = None + language: Optional[str] = None + block_all_marketing_messages: bool = False + blocked_tags: Optional[Dict[str, HashSet[str]]] = None + block_reasons: Optional[List[MarketingBlockReason]] = None + extra_metadata: Optional[str] = None + notes: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ImportUserRowDto: + email: Optional[str] = None + user_name: Optional[str] = None + user_general_info: Optional[UserGeneralInfoDto] = None + roles: Optional[List[str]] = None + created_on: Optional[int] = None + hash_format: Optional[str] = None + password_hash: Optional[str] = None + password_salt: Optional[str] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class DeleteTrigger(CodeMashRequestBase): @@ -3786,12 +4020,19 @@ class PagingArgs: ending_before: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class SchemaUniqueIndexDto: + fields: List[str] = field(default_factory=list) + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class SchemaSettingsDto: soft_delete: bool = False has_record_owner: bool = False description: Optional[str] = None + unique_indexes: Optional[List[SchemaUniqueIndexDto]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -3807,6 +4048,8 @@ class SchemaEmbedSettingsDto: @dataclass class SchemaListColumnDto: field: Optional[str] = None + primary: bool = False + link_reference: bool = False @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -3821,6 +4064,7 @@ class SchemaListSortDto: class SchemaListSettingsDto: columns: List[SchemaListColumnDto] = field(default_factory=list) default_sort: Optional[SchemaListSortDto] = None + filters: List[str] = field(default_factory=list) @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -4025,6 +4269,10 @@ class ChatScreenContextDto: view_id: Optional[str] = None +class INoSessionCookies: + pass + + class EmbeddingProvider(str, Enum): VOYAGE = 'Voyage' OPEN_A_I = 'OpenAI' @@ -4172,6 +4420,15 @@ class TriggerAttentionDto: at_utc: datetime.datetime = datetime.datetime(1, 1, 1) +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TriggerActivationTestProblem: + code: Optional[str] = None + message: Optional[str] = None + line: int = 0 + column: int = 0 + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class AccountOwnerDto: @@ -4261,6 +4518,15 @@ class PromotionBlockerDto: unresolved_ref: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class PromotionTermChangeDto: + taxonomy_id: Optional[str] = None + term_id: Optional[str] = None + slug: Optional[str] = None + change: Optional[str] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class PromotionResultDto: @@ -4270,6 +4536,8 @@ class PromotionResultDto: integrations_to_provision: List[PromotionItemDto] = field(default_factory=list) integrations_skipped: List[PromotionItemDto] = field(default_factory=list) blockers: List[PromotionBlockerDto] = field(default_factory=list) + term_changes: List[PromotionTermChangeDto] = field(default_factory=list) + warnings: List[PromotionBlockerDto] = field(default_factory=list) from_version: Optional[int] = None was_dry_run: bool = False @@ -4493,6 +4761,7 @@ class MembershipDto: triggers: Optional[List[MembershipTriggerDto]] = None custom_roles: Optional[List[RoleItemDto]] = None custom_policies: Optional[List[PolicyItemDto]] = None + system_role_attachments: Optional[List[RoleItemDto]] = None authorization: Optional[AuthorizationDto] = None require_email_validation: bool = False @@ -4640,6 +4909,8 @@ class ProjectListItemDto: unique_name: Optional[str] = None primary_region: Optional[ProjectRegionDto] = None additional_regions: Optional[List[ProjectRegionDto]] = None + modules_count: int = 0 + users_count: int = 0 @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -4804,51 +5075,10 @@ class LoginDto: last_access_information: Optional[AccessInformationDto] = None -class Gender(str, Enum): - MALE = 'Male' - FEMALE = 'Female' - OTHER = 'Other' - - -class MarketingBlockReason(str, Enum): - UNSPECIFIED = 'Unspecified' - UNSUBSCRIBED = 'Unsubscribed' - COMPLAINT = 'Complaint' - HARD_BOUNCE = 'HardBounce' - INVALID_EMAIL = 'InvalidEmail' - ADMIN_BLOCK = 'AdminBlock' - - -@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) -@dataclass -class UserGeneralInfoDto: - phone: Optional[str] = None - primary_email: Optional[str] = None - display_name: Optional[str] = None - first_name: Optional[str] = None - last_name: Optional[str] = None - full_name: Optional[str] = None - address_line1: Optional[str] = None - address_line2: Optional[str] = None - country: Optional[str] = None - city: Optional[str] = None - state: Optional[str] = None - postal_code: Optional[str] = None - company: Optional[str] = None - gender: Optional[Gender] = None - birth_date: Optional[int] = None - time_zone: Optional[str] = None - language: Optional[str] = None - block_all_marketing_messages: bool = False - blocked_tags: Optional[Dict[str, HashSet[str]]] = None - block_reasons: Optional[List[MarketingBlockReason]] = None - extra_metadata: Optional[str] = None - notes: Optional[str] = None - - class AuthStatus(IntEnum): REGISTERED = 0 PENDING_VALIDATION = 2 + INVITED = 4 ACTIVE = 8 UNREGISTERED = 16 SUSPENDED = 32 @@ -5056,6 +5286,48 @@ class AiServiceUserDto: keys: List[AiServiceUserKeyDto] = field(default_factory=list) +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ImportUserErrorDto: + code: Optional[str] = None + message: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ImportUserOutcomeDto: + row: int = 0 + login: Optional[str] = None + outcome: Optional[str] = None + user_id: Optional[str] = None + errors: List[ImportUserErrorDto] = field(default_factory=list) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class UsersImportDto: + dry_run: bool = False + received: int = 0 + imported: int = 0 + valid: int = 0 + existing: int = 0 + invalid: int = 0 + failed: int = 0 + rows: List[ImportUserOutcomeDto] = field(default_factory=list) + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class LoginProjectRepairDto: + dry_run: bool = False + logins_without_project: int = 0 + logins_to_repair: int = 0 + logins_repaired: int = 0 + account_logins_skipped: int = 0 + other_project_logins_skipped: int = 0 + logins_without_evidence: int = 0 + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class ServiceUserApiKeyDto: @@ -5192,6 +5464,14 @@ class MembershipAuthorizationViewDto: deactivation_expiration: Optional[int] = None default_subscribe_to_news: bool = False password_complexity: Optional[PasswordComplexityDto] = None + default_roles: Optional[List[str]] = None + allowed_registration_roles: Optional[List[str]] = None + allow_guest_users: bool = False + guest_cleanup_period_days: Optional[int] = None + allow_email_registration: bool = False + allow_username_registration: bool = False + invite_only: bool = False + allow_anyone_to_sign_up: bool = False @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -5244,6 +5524,7 @@ class TaxonomyDto(IHasViewId): slug: Optional[str] = None parent_id: Optional[str] = None description: Optional[str] = None + env: Optional[str] = None terms_meta_data_schema: Optional[DataSchemaDto] = None terms_meta_visual_schema: Optional[VisualSchemaDto] = None dependencies: Optional[List[str]] = None @@ -5267,6 +5548,7 @@ class TaxonomyListProjection(IHasViewId): dependencies: Optional[List[str]] = None parent_name: Optional[str] = None dependency_refs: Optional[List[TaxonomyRef]] = None + env: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -5322,6 +5604,7 @@ class TermDto: descriptions: Optional[Dict[str, str]] = None multi_parents: Optional[List[TermMultiParentDto]] = None meta: Optional[Object] = None + origin: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -5852,6 +6135,7 @@ class EmailCampaignBatchNotificationDto(CampaignBatchNotificationDto): subject: Optional[str] = None recipients: Optional[EmailRecipientsDto] = None content: Optional[EmailMessageContentDto] = None + transactional_kind: Optional[str] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -6150,6 +6434,14 @@ class PushDeviceListProjection: updated_at_utc: Optional[datetime.datetime] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TeamPushDeviceListProjection(PushDeviceListProjection): + owner_kind: Optional[str] = None + owner_name: Optional[str] = None + owner_email: Optional[str] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class PushAudienceCountDto: @@ -6207,6 +6499,21 @@ class PushCampaignBatchNotificationDto(CampaignBatchNotificationDto): read_by: Optional[List[NotificationReadMarkDto]] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class InAppNotificationDto: + id: Optional[str] = None + project_id: Optional[str] = None + user_id: Optional[str] = None + channel: Optional[str] = None + event_name: Optional[str] = None + payload_json: Optional[str] = None + is_read: bool = False + seen_at_utc: Optional[datetime.datetime] = None + read_at_utc: Optional[datetime.datetime] = None + created_at_utc: datetime.datetime = datetime.datetime(1, 1, 1) + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class PaymentsWebhookLogEntry: @@ -6259,12 +6566,69 @@ class TenantLogEntryDto: @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class AgentOnboardingSnippet: - client: Optional[str] = None - config: Optional[str] = None - auth: Optional[str] = None - kind: Optional[str] = None - recommended: bool = False +class AgentOnboardingSnippet: + client: Optional[str] = None + config: Optional[str] = None + auth: Optional[str] = None + kind: Optional[str] = None + recommended: bool = False + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AiProjectContextCallerWireDto: + kind: Optional[str] = None + name: Optional[str] = None + account_id: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AiProjectContextIntegrationWireDto: + id: Optional[str] = None + name: Optional[str] = None + kind: Optional[str] = None + enabled: Optional[bool] = None + default_in: List[str] = field(default_factory=list) + env: Optional[str] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AiProjectContextModuleWireDto: + name: Optional[str] = None + integrations_readable: Optional[bool] = None + integrations: Optional[List[AiProjectContextIntegrationWireDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AiProjectContextProjectWireDto: + id: Optional[str] = None + name: Optional[str] = None + unique_name: Optional[str] = None + access: Optional[str] = None + description: Optional[str] = None + default_language: Optional[str] = None + languages: List[str] = field(default_factory=list) + environments: Optional[List[str]] = None + primary_region: Optional[str] = None + additional_regions: Optional[List[str]] = None + cors_origins: Optional[List[str]] = None + api_host: Optional[str] = None + admin_url: Optional[str] = None + marketing_url: Optional[str] = None + admin_portal_enabled: Optional[bool] = None + modules: Optional[List[AiProjectContextModuleWireDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class AiProjectContextWireDto: + version: Optional[str] = None + caller: Optional[AiProjectContextCallerWireDto] = None + projects: List[AiProjectContextProjectWireDto] = field(default_factory=list) + hints: List[str] = field(default_factory=list) @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -6770,6 +7134,8 @@ class SchedulerTaskListProjection(IHasViewId): is_failing: bool = False last_failure_reason: Optional[str] = None last_failed_at_unix: Optional[int] = None + ends_at_unix: Optional[int] = None + has_ended: bool = False view_id: Optional[str] = None @@ -7227,12 +7593,26 @@ class PublicLegalDocumentDto: available: bool = False +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetTriggerDefinitionResponse(ResponseBase): + trigger: Optional[SaveTriggerRequest] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class GetTriggersNeedingAttentionResponse(ResponseBase): items: List[TriggerAttentionDto] = field(default_factory=list) +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TestTriggerPreExecuteCodeResponse(ResponseBase): + outcome: Optional[str] = None + trigger_runs: bool = False + problems: List[TriggerActivationTestProblem] = field(default_factory=list) + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class GetAccountProfileResponse(ResponseBase): @@ -7505,6 +7885,18 @@ class RotateAiServiceUserKeyResponse(ResponseBase): key: Optional[str] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ImportUsersResponse(ResponseBase): + result: Optional[UsersImportDto] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class RepairLoginProjectIdsResponse(ResponseBase): + result: Optional[LoginProjectRepairDto] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class IssueServiceUserApiKeyResponse: @@ -8363,6 +8755,7 @@ class GetPushDeviceResponse(ResponseBase): @dataclass class GetPushDevicesResponse(ResponseBase): list: Optional[PaginatedResponse[PushDeviceListProjection]] = None + team_devices: List[TeamPushDeviceListProjection] = field(default_factory=list) @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -8422,6 +8815,30 @@ class GetPushCampaignMessagesResponse(ResponseBase): list: Optional[PaginatedResponse[PushCampaignBatchNotificationDto]] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetNotificationInboxResponse(ResponseBase): + list: Optional[PaginatedResponse[InAppNotificationDto]] = None + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetUnreadCountResponse(ResponseBase): + count: int = 0 + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkNotificationReadResponse(ResponseBase): + pass + + +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkAllNotificationsReadResponse(ResponseBase): + pass + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class GetPaymentsWebhookLogResponse(ResponseBase): @@ -8521,6 +8938,15 @@ class GetAgentOnboardingResponse(ResponseBase): snippets: Optional[List[AgentOnboardingSnippet]] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetAiContextResponse(ResponseBase): + version: Optional[str] = None + unchanged: bool = False + context: Optional[AiProjectContextWireDto] = None + markdown: Optional[str] = None + + @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass class GetAiToolsResponse(ResponseBase): @@ -8600,6 +9026,7 @@ class ValidateSchemaResponse(ResponseBase): valid: bool = False issues: Optional[List[ScaffoldIssue]] = None collections: Optional[List[str]] = None + warnings: Optional[List[ScaffoldIssue]] = None @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -9377,6 +9804,14 @@ class InternalsTypeGen: typegen_53__stripe_payment_integration_request: Optional[StripePaymentIntegrationRequest] = None typegen_54__apple_in_app_payment_integration_request: Optional[AppleInAppPaymentIntegrationRequest] = None typegen_55__google_in_app_payment_integration_request: Optional[GoogleInAppPaymentIntegrationRequest] = None + typegen_285__montonio_payment_integration_request: Optional[MontonioPaymentIntegrationRequest] = None + typegen_287__shopify_payment_integration_request: Optional[ShopifyPaymentIntegrationRequest] = None + typegen_288__woo_commerce_payment_integration_request: Optional[WooCommercePaymentIntegrationRequest] = None + typegen_289__magento_payment_integration_request: Optional[MagentoPaymentIntegrationRequest] = None + typegen_290__braintree_payment_integration_request: Optional[BraintreePaymentIntegrationRequest] = None + typegen_291__authorize_net_payment_integration_request: Optional[AuthorizeNetPaymentIntegrationRequest] = None + typegen_292__check_out_com_payment_integration_request: Optional[CheckOutComPaymentIntegrationRequest] = None + typegen_293__worldpay_payment_integration_request: Optional[WorldpayPaymentIntegrationRequest] = None typegen_56__edge_web_push_integration_request: Optional[EdgeWebPushIntegrationRequest] = None typegen_57__chrome_plugin_push_integration_request: Optional[ChromePluginPushIntegrationRequest] = None typegen_58__safari_push_integration_request: Optional[SafariPushIntegrationRequest] = None @@ -9460,6 +9895,8 @@ class InternalsTypeGen: typegen_188__authorize_net_payment_integration_dto: Optional[AuthorizeNetPaymentIntegrationDto] = None typegen_189__check_out_com_payment_integration_dto: Optional[CheckOutComPaymentIntegrationDto] = None typegen_190__worldpay_payment_integration_dto: Optional[WorldpayPaymentIntegrationDto] = None + typegen_286__montonio_payment_integration_dto: Optional[MontonioPaymentIntegrationDto] = None + typegen_294__payment_order_event_dto: Optional[PaymentOrderEventDto] = None typegen_128__apple_sign_in_membership_integration_dto: Optional[AppleSignInMembershipIntegrationDto] = None typegen_129__git_hub_membership_integration_dto: Optional[GitHubMembershipIntegrationDto] = None typegen_130__google_membership_integration_dto: Optional[GoogleMembershipIntegrationDto] = None @@ -9569,23 +10006,6 @@ class InternalsTypeGen: typegen_243__action_pending_entry_wire_dto: Optional[ActionPendingEntryWireDto] = None typegen_244__notice_entry_wire_dto: Optional[NoticeEntryWireDto] = None typegen_245__conversation_snapshot_entry_wire_dto: Optional[ConversationSnapshotEntryWireDto] = None - typegen_252__string_field_dto: Optional[StringFieldDto] = None - typegen_253__decimal_field_dto: Optional[DecimalFieldDto] = None - typegen_254__currency_field_dto: Optional[CurrencyFieldDto] = None - typegen_255__boolean_field_dto: Optional[BooleanFieldDto] = None - typegen_256__date_field_dto: Optional[DateFieldDto] = None - typegen_257__integer_field_dto: Optional[IntegerFieldDto] = None - typegen_258__geolocation_field_dto: Optional[GeolocationFieldDto] = None - typegen_259__tags_field_dto: Optional[TagsFieldDto] = None - typegen_260__file_field_dto: Optional[FileFieldDto] = None - typegen_261__taxonomy_selection_field_dto: Optional[TaxonomySelectionFieldDto] = None - typegen_262__collection_selection_field_dto: Optional[CollectionSelectionFieldDto] = None - typegen_263__user_selection_field_dto: Optional[UserSelectionFieldDto] = None - typegen_264__role_selection_field_dto: Optional[RoleSelectionFieldDto] = None - typegen_265__enum_selection_field_dto: Optional[EnumSelectionFieldDto] = None - typegen_266__object_field_dto: Optional[ObjectFieldDto] = None - typegen_267__array_field_dto: Optional[ArrayFieldDto] = None - typegen_268__json_field_dto: Optional[JsonFieldDto] = None typegen_269__function_ref_dto: Optional[FunctionRefDto] = None typegen_270__code_function_event_dto: Optional[CodeFunctionEventDto] = None typegen_271__code_function_context_dto: Optional[CodeFunctionContextDto] = None @@ -9604,6 +10024,28 @@ class InternalsTypeGen: typegen_284__marketplace_function_scheduler_task_request: Optional[MarketplaceFunctionSchedulerTaskRequest] = None +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class SharedTypeGen: + typegen__string_field_dto: Optional[StringFieldDto] = None + typegen__decimal_field_dto: Optional[DecimalFieldDto] = None + typegen__currency_field_dto: Optional[CurrencyFieldDto] = None + typegen__boolean_field_dto: Optional[BooleanFieldDto] = None + typegen__date_field_dto: Optional[DateFieldDto] = None + typegen__integer_field_dto: Optional[IntegerFieldDto] = None + typegen__geolocation_field_dto: Optional[GeolocationFieldDto] = None + typegen__tags_field_dto: Optional[TagsFieldDto] = None + typegen__file_field_dto: Optional[FileFieldDto] = None + typegen__taxonomy_selection_field_dto: Optional[TaxonomySelectionFieldDto] = None + typegen__collection_selection_field_dto: Optional[CollectionSelectionFieldDto] = None + typegen__user_selection_field_dto: Optional[UserSelectionFieldDto] = None + typegen__role_selection_field_dto: Optional[RoleSelectionFieldDto] = None + typegen__enum_selection_field_dto: Optional[EnumSelectionFieldDto] = None + typegen__object_field_dto: Optional[ObjectFieldDto] = None + typegen__array_field_dto: Optional[ArrayFieldDto] = None + typegen__json_field_dto: Optional[JsonFieldDto] = None + + # @Route("/{version}/echo", "GET") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass @@ -9635,6 +10077,36 @@ class GetPublicProjectLegal(RequestBase, IReturn[PublicLegalDocumentDto]): kind: Optional[str] = None +# @Route("/{version}/triggers/{id}/definition", "GET") +# @Api(Description="Get one trigger in the shape its save takes (read → change → save)") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetTriggerDefinition(CodeMashRequestBase, IReturn[GetTriggerDefinitionResponse]): + """ + Get one trigger in the shape its save takes (read → change → save) + """ + + # @ApiMember(Description="The trigger id (trg_…).", IsRequired=true) + id: Optional[str] = None + """ + The trigger id (trg_…). + """ + + + # @ApiMember(Description="Which module the trigger belongs to: Schema, Membership, Files, Payments or Ai.", IsRequired=true) + trigger_type: Optional[TriggerType] = None + """ + Which module the trigger belongs to: Schema, Membership, Files, Payments or Ai. + """ + + + # @ApiMember(Description="The collection (schema) id the trigger watches. Required for Schema triggers.") + schema_id: Optional[str] = None + """ + The collection (schema) id the trigger watches. Required for Schema triggers. + """ + + # @Route("/{version}/triggers/attention", "GET") # @Api(Description="Get triggers that need attention") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -9651,6 +10123,57 @@ class GetTriggersNeedingAttention(CodeMashRequestBase, IReturn[GetTriggersNeedin """ +# @Route("/{version}/triggers/pre-execute-code/test", "POST") +# @Api(Description="Test a trigger's pre-action code against a sample record") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class TestTriggerPreExecuteCode(CodeMashRequestBase, IReturn[TestTriggerPreExecuteCodeResponse]): + """ + Test a trigger's pre-action code against a sample record + """ + + # @ApiMember(Description="The code to test, as saved in preExecuteCode: C# statements ending in 'return true;' or 'return false;', e.g. 'return New.status == \"published\";'.", IsRequired=true) + code: Optional[str] = None + """ + The code to test, as saved in preExecuteCode: C# statements ending in 'return true;' or 'return false;', e.g. 'return New.status == "published";'. + """ + + + # @ApiMember(Description="Which kind of trigger the code is for: Schema, Membership, Files, Payments or Ai.", IsRequired=true) + trigger_type: Optional[TriggerType] = None + """ + Which kind of trigger the code is for: Schema, Membership, Files, Payments or Ai. + """ + + + # @ApiMember(Description="The sample record AFTER the change (the code's New), as a JSON object. Omit = empty (a delete).") + new_record: Optional[str] = None + """ + The sample record AFTER the change (the code's New), as a JSON object. Omit = empty (a delete). + """ + + + # @ApiMember(Description="The sample record BEFORE the change (the code's Old), as a JSON object. Omit = empty (an insert).") + old_record: Optional[str] = None + """ + The sample record BEFORE the change (the code's Old), as a JSON object. Omit = empty (an insert). + """ + + + # @ApiMember(Description="What the code sees as Event.Kind: Inserted, Updated, Deleted or Other. Omit = Updated when both records are given, Inserted when only newRecord, Deleted when only oldRecord.") + event_kind: Optional[str] = None + """ + What the code sees as Event.Kind: Inserted, Updated, Deleted or Other. Omit = Updated when both records are given, Inserted when only newRecord, Deleted when only oldRecord. + """ + + + # @ApiMember(Description="What the code sees as Event.Name, e.g. database.record.updated. Optional.") + event_name: Optional[str] = None + """ + What the code sees as Event.Name, e.g. database.record.updated. Optional. + """ + + # @Route("/{version}/account/profile", "GET") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass @@ -10159,10 +10682,10 @@ class UpdateProjectAdminUrl(CodeMashRequestBase, IReturn[EmptyResponse]): Updates the project's admin-portal URL override """ - # @ApiMember(Description="Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr_{id}.admin.{host} address.") + # @ApiMember(Description="Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr-{project hex}.admin.{host} address.") url: Optional[str] = None """ - Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr_{id}.admin.{host} address. + Custom admin-portal URL to use instead of the canonical address. Null/empty restores the canonical pr-{project hex}.admin.{host} address. """ @@ -10442,10 +10965,10 @@ class UpdateProjectAllowedOrigins(CodeMashRequestBase, IReturn[EmptyResponse]): """ - # @ApiMember(Description="Optional. true removes the project's own Admin Portal origin (pr_{projectId}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API.") + # @ApiMember(Description="Optional. true removes the project's own Admin Portal origin (pr-{project hex}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API.") remove_admin_portal_origin: Optional[bool] = None """ - Optional. true removes the project's own Admin Portal origin (pr_{projectId}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API. + Optional. true removes the project's own Admin Portal origin (pr-{project hex}.{admin host}) on purpose. Without it, a list that drops that origin is rejected with CM-ERRORS-PROJECTS-037, because the Norbix-generated end-user portal could no longer call the project's API. """ @@ -11166,6 +11689,24 @@ class RevokeAiServiceUserKeyRequest(RequestBase, IReturn[EmptyResponse]): """ +# @Route("/{version}/account/ai/service-users/{Id}", "PUT") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class UpdateAiServiceUserRequest(RequestBase, IReturn[EmptyResponse]): + # @ApiMember(Description="The service user id (aisu_…).", IsRequired=true) + id: Optional[str] = None + """ + The service user id (aisu_…). + """ + + + # @ApiMember(Description="The new name, unique in the account, e.g. \"Claude Code on my laptop\".", IsRequired=true) + name: Optional[str] = None + """ + The new name, unique in the account, e.g. "Claude Code on my laptop". + """ + + # @Route("/{version}/account/ai/service-users/{Id}", "DELETE") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass @@ -11191,6 +11732,52 @@ class EnableMembership(CodeMashRequestBase, IReturn[EmptyResponse]): pass +# @Route("/{version}/membership/users/import", "POST") +# @Api(Description="Import users with their existing password hashes") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class ImportUsersRequest(CodeMashRequestBase, IReturn[ImportUsersResponse]): + """ + Import users with their existing password hashes + """ + + # @ApiMember(Description="True (default) = check every row and write nothing. False = write.") + dry_run: bool = False + """ + True (default) = check every row and write nothing. False = write. + """ + + + # @ApiMember(Description="True = do not add the project's default roles (as 'ignoreUserRegistersAsRole' on registration).") + ignore_default_roles: bool = False + """ + True = do not add the project's default roles (as 'ignoreUserRegistersAsRole' on registration). + """ + + + # @ApiMember(Description="The users to import, 1 to 1000 per request.", IsRequired=true) + users: List[ImportUserRowDto] = field(default_factory=list) + """ + The users to import, 1 to 1000 per request. + """ + + +# @Route("/{version}/membership/users/repair-logins", "POST") +# @Api(Description="Repair project logins stored without a project id") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class RepairLoginProjectIdsRequest(CodeMashRequestBase, IReturn[RepairLoginProjectIdsResponse]): + """ + Repair project logins stored without a project id + """ + + # @ApiMember(Description="True (default) = only count what would change. False = write.") + dry_run: bool = False + """ + True (default) = only count what would change. False = write. + """ + + # @Route("/{version}/membership/users/{Id}/api-keys", "POST") # @Api(Description="Membership") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -11683,11 +12270,41 @@ class UpdateAuthorizationSettings(CodeMashRequestBase, IReturn[EmptyResponse]): Updates the project's membership authorization settings. """ + # @ApiMember(Description="Single-setting change (dashboard tabs), e.g. 'DefaultRegisterRole' with userRegistersAsRole, or 'PasswordComplexity'. Unknown values are refused. Leave empty to change defaultRoles / allowedRegistrationRoles / allowGuestUsers / guestCleanupPeriodDays — only the fields you send change.") setting: Optional[str] = None + """ + Single-setting change (dashboard tabs), e.g. 'DefaultRegisterRole' with userRegistersAsRole, or 'PasswordComplexity'. Unknown values are refused. Leave empty to change defaultRoles / allowedRegistrationRoles / allowGuestUsers / guestCleanupPeriodDays — only the fields you send change. + """ + + + # @ApiMember(Description="Role names given to a user who registers without naming roles. Omit = keep; [] = none.") default_roles: Optional[List[str]] = None + """ + Role names given to a user who registers without naming roles. Omit = keep; [] = none. + """ + + + # @ApiMember(Description="Role names a user may pick when registering. Omit = keep; [] = none.") allowed_registration_roles: Optional[List[str]] = None - allow_guest_users: bool = False + """ + Role names a user may pick when registering. Omit = keep; [] = none. + """ + + + # @ApiMember(Description="Whether guest (anonymous) users may be created. Omit = keep. When sent, guestCleanupPeriodDays is taken with it (null = never clean up).") + allow_guest_users: Optional[bool] = None + """ + Whether guest (anonymous) users may be created. Omit = keep. When sent, guestCleanupPeriodDays is taken with it (null = never clean up). + """ + + + # @ApiMember(Description="Days after which inactive guests are removed; null or 0 = never. Omit both guest fields = keep.") guest_cleanup_period_days: Optional[int] = None + """ + Days after which inactive guests are removed; null or 0 = never. Omit both guest fields = keep. + """ + + user_registers_as_role: Optional[str] = None guest_registers_as_role: Optional[str] = None allowed_register_roles: Optional[List[str]] = None @@ -11701,6 +12318,27 @@ class UpdateAuthorizationSettings(CodeMashRequestBase, IReturn[EmptyResponse]): email_verification_expiration: Optional[int] = None deactivation_expiration: Optional[int] = None default_subscribe_to_news: bool = False + # @ApiMember(Description="\"Email registration\": the public register/email route accepts sign-ups. Omit = keep.") + allow_email_registration: Optional[bool] = None + """ + "Email registration": the public register/email route accepts sign-ups. Omit = keep. + """ + + + # @ApiMember(Description="\"Invite-only\": public sign-up (email and username) is refused; only invitations create users. Omit = keep.") + invite_only: Optional[bool] = None + """ + "Invite-only": public sign-up (email and username) is refused; only invitations create users. Omit = keep. + """ + + + # @ApiMember(Description="\"Allow anyone to sign up\": grants (true) / revokes (false) membership:register on the project's Guest role. Omit = keep.") + allow_anyone_to_sign_up: Optional[bool] = None + """ + "Allow anyone to sign up": grants (true) / revokes (false) membership:register on the project's Guest role. Omit = keep. + """ + + min_length: int = 0 max_length: Optional[int] = None min_numbers: Optional[int] = None @@ -12069,10 +12707,10 @@ class DeleteDatabaseTaxonomyTermRequest(CodeMashRequestBase, IReturn[EmptyRespon Delete a single term from a taxonomy by id """ - # @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) taxonomy_id: Optional[str] = None """ - Taxonomy id that owns the term, from get_database_taxonomies. + Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title). """ @@ -12099,10 +12737,10 @@ class DeleteManyDatabaseTaxonomyTermsRequest(CodeMashRequestBase, IReturn[EmptyR Delete many terms in a taxonomy matching the given filter """ - # @ApiMember(Description="Taxonomy id whose terms to delete, from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy id whose terms to delete, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) taxonomy_id: Optional[str] = None """ - Taxonomy id whose terms to delete, from get_database_taxonomies. + Taxonomy id whose terms to delete, from get_database_taxonomies — or the taxonomy name (slug or title). """ @@ -12136,10 +12774,10 @@ class GetDatabaseTaxonomyTermRequest(CodeMashRequestBase, IReturn[GetDatabaseTax """ - # @ApiMember(Description="Taxonomy id from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy id from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) taxonomy_id: Optional[str] = None """ - Taxonomy id from get_database_taxonomies. + Taxonomy id from get_database_taxonomies — or the taxonomy name (slug or title). """ @@ -12173,10 +12811,10 @@ class GetDatabaseMergedTermTreeRequest(CodeMashRequestBase, IReturn[GetDatabaseM """ - # @ApiMember(Description="Root taxonomy slug/name (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them.", IsRequired=true) + # @ApiMember(Description="Root taxonomy slug/name or id, txn_… (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them.", IsRequired=true) taxonomy_name: Optional[str] = None """ - Root taxonomy slug/name (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them. + Root taxonomy slug/name or id, txn_… (from get_database_taxonomies). Its terms are the roots; child-taxonomy terms nest under them. """ @@ -12203,10 +12841,10 @@ class GetDatabaseTaxonomyTermTreeRequest(CodeMashRequestBase, IReturn[GetDatabas """ - # @ApiMember(Description="Taxonomy slug/name to fetch the term tree for, from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy slug/name (or its id, txn_…) to fetch the term tree for, from get_database_taxonomies.", IsRequired=true) taxonomy_name: Optional[str] = None """ - Taxonomy slug/name to fetch the term tree for, from get_database_taxonomies. + Taxonomy slug/name (or its id, txn_…) to fetch the term tree for, from get_database_taxonomies. """ @@ -12240,10 +12878,10 @@ class SaveDatabaseTaxonomyTermRequest(CodeMashRequestBase, IReturn[IdResponse]): Insert a single term into a taxonomy """ - # @ApiMember(Description="Taxonomy id to insert the term into, from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy id to insert the term into, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) taxonomy_id: Optional[str] = None """ - Taxonomy id to insert the term into, from get_database_taxonomies. + Taxonomy id to insert the term into, from get_database_taxonomies — or the taxonomy name (slug or title). """ @@ -12270,10 +12908,10 @@ class UpdateDatabaseTaxonomyTermRequest(CodeMashRequestBase, IReturn[EmptyRespon Update a single term in a taxonomy by id """ - # @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies.", IsRequired=true) + # @ApiMember(Description="Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title).", IsRequired=true) taxonomy_id: Optional[str] = None """ - Taxonomy id that owns the term, from get_database_taxonomies. + Taxonomy id that owns the term, from get_database_taxonomies — or the taxonomy name (slug or title). """ @@ -16202,10 +16840,10 @@ class TestPushIntegration(CodeMashRequestBase, IReturn[TestEmailIntegrationRespo """ - # @ApiMember(Description="The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Fake integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily.") + # @ApiMember(Description="The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Sandbox integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily.") test_token: Optional[str] = None """ - The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Fake integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily. + The device token the test is sent to — a device registered for the person receiving the test (get it from get_push_devices). Required for every real provider (only the Sandbox integration tests without one). For a web device it is the browser subscription JSON. Requires DeliveryFamily. """ @@ -16641,6 +17279,35 @@ class GetPushCampaignMessagesRequest(CodeMashListPaginationRequestBase, IReturn[ """ +# @Route("/{version}/notifications/inbox", "GET") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetNotificationInboxRequest(CodeMashListPaginationRequestBase, IReturn[GetNotificationInboxResponse]): + unread_only: bool = False + channel: Optional[str] = None + + +# @Route("/{version}/notifications/inbox/unread-count", "GET") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetUnreadCountRequest(CodeMashRequestBase, IReturn[GetUnreadCountResponse]): + pass + + +# @Route("/{version}/notifications/inbox/{notificationId}/read", "POST") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkNotificationReadRequest(CodeMashRequestBase, IReturn[MarkNotificationReadResponse]): + notification_id: Optional[str] = None + + +# @Route("/{version}/notifications/inbox/read-all", "POST") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class MarkAllNotificationsReadRequest(CodeMashRequestBase, IReturn[MarkAllNotificationsReadResponse]): + pass + + # @Route("/{version}/payments/disable", "PUT") # @Api(Description="Disable payments service") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -17163,6 +17830,20 @@ class GetAgentOnboardingRequest(RequestBase, IReturn[GetAgentOnboardingResponse] pass +# @Route("/{version}/account/ai/context", "GET") +# @Api(Description="The AI project-context summary: the projects the caller may work on, with their settings — never a secret.") +@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) +@dataclass +class GetAiContextRequest(RequestBase, IReturn[GetAiContextResponse]): + """ + The AI project-context summary: the projects the caller may work on, with their settings — never a secret. + """ + + project_id: Optional[str] = None + format: Optional[str] = None + known_version: Optional[str] = None + + # @Route("/{version}/account/ai/tools", "GET") # @Api(Description="Lists the AI tools this host exposes (external-agent bridge).") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @@ -17657,7 +18338,7 @@ class DeleteAiProjectTrigger(DeleteTrigger, IReturn[EmptyResponse]): # @Api(Description="Starts a browser sign-in for the Norbix CLI (OAuth device authorization, RFC 8628): a device code for polling and a user code the person confirms on the dashboard.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class AuthDeviceStartRequest(RequestBase, IReturn[AuthDeviceStartResponse]): +class AuthDeviceStartRequest(RequestBase, IReturn[AuthDeviceStartResponse], INoSessionCookies): """ Starts a browser sign-in for the Norbix CLI (OAuth device authorization, RFC 8628): a device code for polling and a user code the person confirms on the dashboard. """ @@ -17687,7 +18368,7 @@ class AuthDeviceStartRequest(RequestBase, IReturn[AuthDeviceStartResponse]): # @Api(Description="Polls a CLI browser sign-in (RFC 8628). Always HTTP 200: an error name (authorization_pending, slow_down, access_denied, expired_token, invalid_grant, invalid_request) or the tokens, once.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class AuthDeviceTokenRequest(RequestBase, IReturn[AuthDeviceTokenResponse]): +class AuthDeviceTokenRequest(RequestBase, IReturn[AuthDeviceTokenResponse], INoSessionCookies): """ Polls a CLI browser sign-in (RFC 8628). Always HTTP 200: an error name (authorization_pending, slow_down, access_denied, expired_token, invalid_grant, invalid_request) or the tokens, once. """ @@ -17757,7 +18438,7 @@ class AuthDeviceConsentDecisionRequest(RequestBase, IReturn[AuthDeviceConsentDec # @Api(Description="OAuth protected-resource metadata (RFC 9728) for the Hub MCP endpoint.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthProtectedResourceMetadataRequest(IReturn[str]): +class OAuthProtectedResourceMetadataRequest(IReturn[str], INoSessionCookies): """ OAuth protected-resource metadata (RFC 9728) for the Hub MCP endpoint. """ @@ -17770,7 +18451,7 @@ class OAuthProtectedResourceMetadataRequest(IReturn[str]): # @Api(Description="OAuth authorization-server metadata (RFC 8414).") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthAuthorizationServerMetadataRequest(IReturn[str]): +class OAuthAuthorizationServerMetadataRequest(IReturn[str], INoSessionCookies): """ OAuth authorization-server metadata (RFC 8414). """ @@ -17782,7 +18463,7 @@ class OAuthAuthorizationServerMetadataRequest(IReturn[str]): # @Api(Description="Registers an MCP client for OAuth (RFC 7591). Public clients only: PKCE, no secret.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthRegisterRequest(IReturn[str]): +class OAuthRegisterRequest(IReturn[str], INoSessionCookies): """ Registers an MCP client for OAuth (RFC 7591). Public clients only: PKCE, no secret. """ @@ -17795,7 +18476,7 @@ class OAuthRegisterRequest(IReturn[str]): # @Api(Description="OAuth authorization endpoint: checks the request and redirects to the dashboard consent screen.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthAuthorizeRequest(IReturn[str]): +class OAuthAuthorizeRequest(IReturn[str], INoSessionCookies): """ OAuth authorization endpoint: checks the request and redirects to the dashboard consent screen. """ @@ -17965,7 +18646,7 @@ class OAuthConsentDecisionRequest(RequestBase, IReturn[OAuthConsentDecisionRespo # @Api(Description="OAuth token endpoint: authorization code (PKCE S256) or refresh token → access token.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthTokenRequest(IReturn[str]): +class OAuthTokenRequest(IReturn[str], INoSessionCookies): """ OAuth token endpoint: authorization code (PKCE S256) or refresh token → access token. """ @@ -17977,7 +18658,7 @@ class OAuthTokenRequest(IReturn[str]): # @Api(Description="OAuth token revocation (RFC 7009): revokes the grant behind a refresh or access token.") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) @dataclass -class OAuthRevokeRequest(IReturn[str]): +class OAuthRevokeRequest(IReturn[str], INoSessionCookies): """ OAuth token revocation (RFC 7009): revokes the grant behind a refresh or access token. """ @@ -18410,6 +19091,7 @@ class SaveSchedulerTaskRequest(CodeMashRequestBase, IReturn[IdResponse]): initiator_user_id: Optional[str] = None is_enabled: bool = False stop_on_error: bool = False + ends_at_unix: Optional[int] = None task: Optional[SchedulerTaskRequest] = None @@ -18519,10 +19201,10 @@ class GetContact(CodeMashRequestBase, IReturn[GetContactResponse]): Get a contact """ - # @ApiMember(Description="The contact id (ct_…) to fetch. Get it from get_all_contacts.", IsRequired=true) + # @ApiMember(Description="The contact id (ct_…) to fetch, or a login id (usr_…) — then the contact that owns that login is returned. Get it from get_all_contacts.", IsRequired=true) contact_id: Optional[str] = None """ - The contact id (ct_…) to fetch. Get it from get_all_contacts. + The contact id (ct_…) to fetch, or a login id (usr_…) — then the contact that owns that login is returned. Get it from get_all_contacts. """ @@ -18549,6 +19231,48 @@ class GetAllContacts(CodeMashRequestBase, IReturn[GetAllContactsResponse]): """ + # @ApiMember(Description="Free text, case-insensitive: matches the email, phone, display / first / last / full name, or any login's user name or email.") + search: Optional[str] = None + """ + Free text, case-insensitive: matches the email, phone, display / first / last / full name, or any login's user name or email. + """ + + + # @ApiMember(Description="Case-insensitive part of the email (primary email or any login's email).") + email: Optional[str] = None + """ + Case-insensitive part of the email (primary email or any login's email). + """ + + + # @ApiMember(Description="Case-insensitive part of any login's user name.") + user_name: Optional[str] = None + """ + Case-insensitive part of any login's user name. + """ + + + # @ApiMember(Description="Login status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked.") + statuses: Optional[List[str]] = None + """ + Login status names, any of: Registered, PendingValidation, Active, Unregistered, Suspended, InActive, Blocked. + """ + + + # @ApiMember(Description="Login type names, any of: Service, Email, UserName, Phone, Guest, Social.") + types: Optional[List[str]] = None + """ + Login type names, any of: Service, Email, UserName, Phone, Guest, Social. + """ + + + # @ApiMember(Description="Composite project-role ids (pr_{project}_nr_{role}); the contact holds any of them.") + role_names: Optional[List[str]] = None + """ + Composite project-role ids (pr_{project}_nr_{role}); the contact holds any of them. + """ + + # @Route("/{version}/membership/users/merge", "POST") # @Api(Description="Merge contacts") @dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE) diff --git a/src/norbix_python/api/__init__.py b/src/norbix_python/api/__init__.py index f64b205..879cc6e 100644 --- a/src/norbix_python/api/__init__.py +++ b/src/norbix_python/api/__init__.py @@ -6,6 +6,7 @@ from .echo import AsyncEchoModule, EchoModule from .files import AsyncFilesModule, FilesModule from .membership import AsyncMembershipModule, MembershipModule +from .payments import AsyncPaymentsModule, PaymentsModule from .public import AsyncPublicModule, PublicModule @@ -16,6 +17,7 @@ def __init__(self, transport: Transport) -> None: self.echo = EchoModule(transport) self.files = FilesModule(transport) self.membership = MembershipModule(transport) + self.payments = PaymentsModule(transport) self.public = PublicModule(transport) @@ -26,4 +28,5 @@ def __init__(self, transport: AsyncTransport) -> None: self.echo = AsyncEchoModule(transport) self.files = AsyncFilesModule(transport) self.membership = AsyncMembershipModule(transport) + self.payments = AsyncPaymentsModule(transport) self.public = AsyncPublicModule(transport) diff --git a/src/norbix_python/api/payments.py b/src/norbix_python/api/payments.py new file mode 100644 index 0000000..52b663f --- /dev/null +++ b/src/norbix_python/api/payments.py @@ -0,0 +1,175 @@ +"""Payment orders and checkout on the Api (project scope). + +A payment order is what a buyer pays for: lines priced in minor units, a +merchant reference and a price version. Create it, start a provider checkout +(Montonio, …) and send the buyer to ``checkout["paymentUrl"]``. A verified +provider callback moves the order on; a destination or Code function hears it +as ``payments.order.paid`` / ``…refunded`` / ``…expired`` (see +``NorbixWebhookEvents.Payments`` and ``FunctionEvent.as_payment_order``). +""" + +from __future__ import annotations + +from typing import Any + +from ..transport import AsyncTransport, Transport + + +class PaymentsModule: + def __init__(self, transport: Transport) -> None: + self._transport = transport + + def create_payment_order(self, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """POST /{version}/payments/orders + + Create a payment order for a buyer: ``buyerUserId``, ``merchantReference``, + ``currency``, ``priceVersion``, ``lines`` (each ``sku``, ``title``, + ``quantity``, ``unitAmountMinor``), optional ``idempotencyKey`` and + ``metadata`` (a string map). Gives back ``{"id": "ord_…"}``; the same body + with the same ``idempotencyKey`` gives back the same id. + """ + return self._transport.send( + target="api", + path="/{version}/payments/orders", + method="POST", + path_params={}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + def get_payment_order(self, id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """GET /{version}/payments/orders/{Id} + + One payment order by its id (``ord_…``). Gives back ``{"item": order}`` + (lines, totals, status, checkouts, ``settledMinor``, ``refundedMinor``, …). + """ + return self._transport.send( + target="api", + path="/{version}/payments/orders/{Id}", + method="GET", + path_params={"Id": id}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + def get_payment_orders(self, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """GET /{version}/payments/orders + + The payment orders of the project, filtered by the optional + ``buyerUserId``, ``merchantReference`` and ``status`` (query). Gives back + ``{"list": {"items": [...], ...}}``. + """ + return self._transport.send( + target="api", + path="/{version}/payments/orders", + method="GET", + path_params={}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + def start_payment_checkout(self, id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """POST /{version}/payments/orders/{Id}/checkout + + Start (or reuse) the provider checkout of an order: ``integrationId``, + ``returnUrl``, optional ``method``, ``preferredCountry`` and + ``preferredProvider``. Gives back ``checkout`` (``paymentUrl`` to send the + buyer to, ``expiresAtUtc``, …), ``reused`` (an open checkout was handed + back) and the ``order``. + """ + return self._transport.send( + target="api", + path="/{version}/payments/orders/{Id}/checkout", + method="POST", + path_params={"Id": id}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + +class AsyncPaymentsModule: + def __init__(self, transport: AsyncTransport) -> None: + self._transport = transport + + async def create_payment_order(self, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """POST /{version}/payments/orders + + Create a payment order for a buyer: ``buyerUserId``, ``merchantReference``, + ``currency``, ``priceVersion``, ``lines`` (each ``sku``, ``title``, + ``quantity``, ``unitAmountMinor``), optional ``idempotencyKey`` and + ``metadata`` (a string map). Gives back ``{"id": "ord_…"}``; the same body + with the same ``idempotencyKey`` gives back the same id. + """ + return await self._transport.send( + target="api", + path="/{version}/payments/orders", + method="POST", + path_params={}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + async def get_payment_order(self, id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """GET /{version}/payments/orders/{Id} + + One payment order by its id (``ord_…``). Gives back ``{"item": order}`` + (lines, totals, status, checkouts, ``settledMinor``, ``refundedMinor``, …). + """ + return await self._transport.send( + target="api", + path="/{version}/payments/orders/{Id}", + method="GET", + path_params={"Id": id}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + async def get_payment_orders(self, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """GET /{version}/payments/orders + + The payment orders of the project, filtered by the optional + ``buyerUserId``, ``merchantReference`` and ``status`` (query). Gives back + ``{"list": {"items": [...], ...}}``. + """ + return await self._transport.send( + target="api", + path="/{version}/payments/orders", + method="GET", + path_params={}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) + + async def start_payment_checkout(self, id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any: + """POST /{version}/payments/orders/{Id}/checkout + + Start (or reuse) the provider checkout of an order: ``integrationId``, + ``returnUrl``, optional ``method``, ``preferredCountry`` and + ``preferredProvider``. Gives back ``checkout`` (``paymentUrl`` to send the + buyer to, ``expiresAtUtc``, …), ``reused`` (an open checkout was handed + back) and the ``order``. + """ + return await self._transport.send( + target="api", + path="/{version}/payments/orders/{Id}/checkout", + method="POST", + path_params={"Id": id}, + request=request, + scope="project", + timeout=timeout, + bearer_token=bearer_token, + ) diff --git a/src/norbix_python/client.py b/src/norbix_python/client.py index 7d1c856..257cff7 100644 --- a/src/norbix_python/client.py +++ b/src/norbix_python/client.py @@ -264,11 +264,13 @@ def __init__( self.membership = api.membership self.echo = api.echo self.files = api.files + self.payments = api.payments self.public = api.public self.Database = self.database self.Membership = self.membership self.Echo = self.echo self.Files = self.files + self.Payments = self.payments self.Public = self.public def close(self) -> None: diff --git a/src/norbix_python/functions.py b/src/norbix_python/functions.py index 8e2e719..2d6f7d6 100644 --- a/src/norbix_python/functions.py +++ b/src/norbix_python/functions.py @@ -234,6 +234,11 @@ def provider_event_id(self) -> str | None: def event_name(self) -> str | None: return self.raw.get("eventName") + @property + def order_id(self) -> str | None: + """The payment order (``ord_…``) the callback is about, when it is about one.""" + return self.raw.get("orderId") + @property def status(self) -> str | None: return self.raw.get("status") @@ -259,6 +264,137 @@ def received_on(self) -> str | None: return self.raw.get("receivedOn") +class PaymentOrder(_View): + """A stored payment order (``PaymentOrderDto``): lines, totals and status. + + ``lines`` and ``checkouts`` are the raw dicts (``sku``, ``title``, + ``quantity``, ``unitAmountMinor``, ``amountMinor`` / ``attempt``, + ``integrationId``, ``provider``, ``paymentUrl``, ``expiresAtUtc``, …). + """ + + @property + def id(self) -> str | None: + return self.raw.get("id") + + @property + def env(self) -> str | None: + return self.raw.get("env") + + @property + def buyer_user_id(self) -> str | None: + return self.raw.get("buyerUserId") + + @property + def merchant_reference(self) -> str | None: + return self.raw.get("merchantReference") + + @property + def currency(self) -> str | None: + return self.raw.get("currency") + + @property + def price_version(self) -> str | None: + return self.raw.get("priceVersion") + + @property + def lines(self) -> list[dict[str, Any]]: + value = self.raw.get("lines") + return [line for line in value if isinstance(line, dict)] if isinstance(value, list) else [] + + @property + def total_minor(self) -> int | None: + return self.raw.get("totalMinor") + + @property + def metadata(self) -> dict[str, str]: + return _as_dict(self.raw.get("metadata")) + + @property + def status(self) -> str | None: + """The order status after the last change. + + ``Created``, ``CheckoutStarted``, ``Paid``, ``PartiallyRefunded``, + ``Refunded``, ``Reversed``, ``Expired``, … + """ + return self.raw.get("status") + + @property + def created_on_utc(self) -> str | None: + return self.raw.get("createdOnUtc") + + @property + def updated_on_utc(self) -> str | None: + return self.raw.get("updatedOnUtc") + + @property + def checkouts(self) -> list[dict[str, Any]]: + value = self.raw.get("checkouts") + return [c for c in value if isinstance(c, dict)] if isinstance(value, list) else [] + + @property + def settled_minor(self) -> int | None: + return self.raw.get("settledMinor") + + @property + def refunded_minor(self) -> int | None: + return self.raw.get("refundedMinor") + + @property + def paid_on_utc(self) -> str | None: + return self.raw.get("paidOnUtc") + + @property + def provider_payment_id(self) -> str | None: + return self.raw.get("providerPaymentId") + + @property + def mismatches(self) -> list[str]: + value = self.raw.get("mismatches") + return list(value) if isinstance(value, list) else [] + + +class PaymentOrderEvent(_View): + """`data.order` — a stored payment order changed (``payments.order.*``). + + ``order`` is the order as stored after the change; ``payment`` is the + provider callback that changed it. ``order_event_id`` is the + de-duplication key: it is the same on every retry of the same change. + """ + + @property + def order_event_id(self) -> str | None: + """The de-duplication key — the same on every retry of this change.""" + return self.raw.get("orderEventId") + + @property + def event(self) -> str | None: + """The event name: ``payments.order.paid``, ``…refunded``, ``…expired``, …""" + return self.raw.get("event") + + @property + def from_(self) -> str | None: + """The order status before the change (``from`` on the wire).""" + return self.raw.get("from") + + @property + def to(self) -> str | None: + """The order status after the change.""" + return self.raw.get("to") + + @property + def reason(self) -> str | None: + return self.raw.get("reason") + + @property + def order(self) -> PaymentOrder: + return PaymentOrder(self.raw.get("order")) + + @property + def payment(self) -> PaymentFact | None: + value = self.raw.get("payment") + return PaymentFact(value) if isinstance(value, dict) else None + + class ScheduledTaskInfo(_View): """`data.task` — the scheduler task that fired (`scheduler.task.fired`).""" @@ -373,9 +509,20 @@ def as_file_change(self) -> FileChange: return FileChange(self._slot("file")) def as_payment(self) -> PaymentFact: - """`data.payment` — Payments triggers.""" + """`data.payment` — Payments triggers. + + On ``payments.order.*`` it is the provider callback that changed the order. + """ return PaymentFact(self._slot("payment")) + def as_payment_order(self) -> PaymentOrderEvent: + """`data.order` — Payments order triggers (``payments.order.*``). + + The order as stored after the change; de-duplicate on + ``order_event_id``. :meth:`as_payment` still returns the callback. + """ + return PaymentOrderEvent(self._slot("order")) + def as_scheduled_task(self) -> ScheduledTaskInfo: """`data.task` — a scheduler task fire.""" return ScheduledTaskInfo(self._slot("task")) @@ -452,6 +599,8 @@ def parse_function_event(raw: str | bytes | bytearray | dict[str, Any]) -> Funct "FunctionEvent", "NorbixFunctionEventError", "PaymentFact", + "PaymentOrder", + "PaymentOrderEvent", "RunAs", "ScheduledTaskInfo", "UserChange", diff --git a/src/norbix_python/webhooks/__init__.py b/src/norbix_python/webhooks/__init__.py index 947dcfe..8befebc 100644 --- a/src/norbix_python/webhooks/__init__.py +++ b/src/norbix_python/webhooks/__init__.py @@ -19,6 +19,7 @@ WebhookEvent, WebhookEventMetadata, WebhookHandleResult, + WebhookOrderRef, WebhookPaymentRef, WebhookRecordIds, WebhookSchemaInfo, @@ -41,6 +42,7 @@ "AsyncNorbixWebhookReceiver", "FileDeleted", "FileResourceRef", + "WebhookOrderRef", "WebhookPaymentRef", "Mutation", "NorbixWebhookError", diff --git a/src/norbix_python/webhooks/events.py b/src/norbix_python/webhooks/events.py index 988aa85..8686ea6 100644 --- a/src/norbix_python/webhooks/events.py +++ b/src/norbix_python/webhooks/events.py @@ -23,6 +23,11 @@ "files.file.uploaded", "files.file.deleted", "payments.webhook.received", + "payments.order.paid", + "payments.order.partially_refunded", + "payments.order.refunded", + "payments.order.reversed", + "payments.order.expired", ) @@ -61,3 +66,17 @@ class Payments: #: project's payments webhook. The payload is the normalized payment fact #: (``PaymentFact``); the provider's own event name is ``payload.event_name``. WEBHOOK_RECEIVED: Final = "payments.webhook.received" + #: A verified provider callback made a stored payment order Paid. The + #: payload is the order event (``PaymentOrderEvent``): ``payload.order`` + #: is the order as stored after the change, ``payload.payment`` the + #: callback. De-duplicate on ``payload.order_event_id`` (also + #: ``event.metadata.order.order_event_id``) — it is the same on every retry. + ORDER_PAID: Final = "payments.order.paid" + #: Part of a paid order was refunded (``payload.order.refunded_minor``). + ORDER_PARTIALLY_REFUNDED: Final = "payments.order.partially_refunded" + #: The whole order was refunded. + ORDER_REFUNDED: Final = "payments.order.refunded" + #: The provider reversed (voided) the payment. + ORDER_REVERSED: Final = "payments.order.reversed" + #: The checkout ran out without a payment. + ORDER_EXPIRED: Final = "payments.order.expired" diff --git a/src/norbix_python/webhooks/models.py b/src/norbix_python/webhooks/models.py index 1677844..2cdfb96 100644 --- a/src/norbix_python/webhooks/models.py +++ b/src/norbix_python/webhooks/models.py @@ -81,6 +81,18 @@ class WebhookPaymentRef(_Model): event_name: str = Field(alias="eventName") +class WebhookOrderRef(_Model): + """The stored order of a payments.order.* delivery. + + ``order_event_id`` is the de-duplication key: the same on every retry of + the same order change. + """ + + id: str + order_event_id: str = Field(alias="orderEventId") + status: str + + class WebhookRecordIds(_Model): """Batch record ids.""" @@ -104,6 +116,9 @@ class WebhookEventMetadata(_Model): #: payments.* events: the provider and its own event id / name #: (e.g. ``Stripe``, ``evt_…``, ``payment_intent.succeeded``). payment: WebhookPaymentRef | None = None + #: payments.order.* events: the order id, its status after the change + #: and ``order_event_id`` — the de-duplication key. + order: WebhookOrderRef | None = None class WebhookEnvelope(_Model): diff --git a/src/norbix_python/webhooks/normalize.py b/src/norbix_python/webhooks/normalize.py index ef9b9b3..c9b7ab4 100644 --- a/src/norbix_python/webhooks/normalize.py +++ b/src/norbix_python/webhooks/normalize.py @@ -2,7 +2,7 @@ from typing import Any -from ..functions import PaymentFact +from ..functions import PaymentFact, PaymentOrderEvent from .models import ( FileDeleted, FileResourceRef, @@ -12,6 +12,7 @@ WebhookEntityRef, WebhookEnvelope, WebhookEventMetadata, + WebhookOrderRef, WebhookPaymentRef, WebhookRecordIds, WebhookSchemaInfo, @@ -88,17 +89,31 @@ def normalize_webhook(envelope: WebhookEnvelope) -> tuple[Any, WebhookEventMetad return envelope.data, metadata if event.startswith("payments."): - # The whole data object IS the normalized payment fact (the same shape - # as a Code function's ``data.payment``); the provider ids are lifted - # onto metadata so a handler can de-duplicate on them. - if isinstance(data.get("integrationId"), str): - metadata.integration_id = data["integrationId"] - if all(isinstance(data.get(k), str) for k in ("provider", "providerEventId", "eventName")): + # payments.webhook.received: the whole data object IS the normalized + # payment fact (the same shape as a Code function's ``data.payment``). + # payments.order.*: the data is the order event; its ``payment`` is the + # fact. Either way the provider ids are lifted onto metadata so a + # handler can de-duplicate on them. + is_order_event = event.startswith("payments.order.") + fact = _as_dict(data.get("payment")) if is_order_event else data + if isinstance(fact.get("integrationId"), str): + metadata.integration_id = fact["integrationId"] + if all(isinstance(fact.get(k), str) for k in ("provider", "providerEventId", "eventName")): metadata.payment = WebhookPaymentRef( - provider=data["provider"], - providerEventId=data["providerEventId"], - eventName=data["eventName"], + provider=fact["provider"], + providerEventId=fact["providerEventId"], + eventName=fact["eventName"], ) - return PaymentFact(_as_dict(data)), metadata + if is_order_event: + order = _as_dict(data.get("order")) + ids = (order.get("id"), data.get("orderEventId"), order.get("status")) + if all(isinstance(v, str) for v in ids): + metadata.order = WebhookOrderRef( + id=order["id"], + orderEventId=data["orderEventId"], + status=order["status"], + ) + return PaymentOrderEvent(data), metadata + return PaymentFact(data), metadata return envelope.data, metadata diff --git a/tests/api/test_payments.py b/tests/api/test_payments.py new file mode 100644 index 0000000..15ffc8a --- /dev/null +++ b/tests/api/test_payments.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +import asyncio +import json +from urllib.parse import parse_qs, urlparse + +import httpx + +from norbix_python import AsyncNorbix + +from ..helpers import make_client + + +def test_api_payments_module_surface() -> None: + client, _ = make_client() + module = client.api.payments + assert callable(module.create_payment_order) + assert callable(module.get_payment_order) + assert callable(module.get_payment_orders) + assert callable(module.start_payment_checkout) + + +def test_api_payments_create_payment_order_request_shape() -> None: + client, transport = make_client(account_id=None) + client.api.payments.create_payment_order( + buyerUserId="usr_1", + merchantReference="ad-1042-promo-1", + idempotencyKey="idem-key-1", + currency="EUR", + priceVersion="v1", + lines=[{"sku": "star-day", "quantity": 21, "unitAmountMinor": 30}], + metadata={"adId": "ad_1042"}, + ) + assert transport.last_request is not None + assert transport.last_request['method'] == 'POST' + assert urlparse(transport.last_request['url']).path == '/v3/payments/orders' + body = json.loads(transport.last_request['body']) + assert body['buyerUserId'] == 'usr_1' + assert body['idempotencyKey'] == 'idem-key-1' + assert body['lines'] == [{"sku": "star-day", "quantity": 21, "unitAmountMinor": 30}] + assert body['metadata'] == {"adId": "ad_1042"} + + +def test_api_payments_get_payment_order_request_shape() -> None: + client, transport = make_client(account_id=None) + client.api.payments.get_payment_order("ord_1") + assert transport.last_request is not None + assert transport.last_request['method'] == 'GET' + assert urlparse(transport.last_request['url']).path == '/v3/payments/orders/ord_1' + assert transport.last_request['body'] == '' + + +def test_api_payments_get_payment_orders_request_shape() -> None: + client, transport = make_client(account_id=None) + client.api.payments.get_payment_orders(buyerUserId="usr_1", merchantReference="ad-1042", status="Paid") + assert transport.last_request is not None + assert transport.last_request['method'] == 'GET' + url = urlparse(transport.last_request['url']) + assert url.path == '/v3/payments/orders' + assert parse_qs(url.query) == {"buyerUserId": ["usr_1"], "merchantReference": ["ad-1042"], "status": ["Paid"]} + + +def test_api_payments_start_payment_checkout_request_shape() -> None: + client, transport = make_client(account_id=None) + client.api.payments.start_payment_checkout( + "ord_1", + integrationId="int_montonio", + returnUrl="https://shop.example.test/return", + preferredCountry="LT", + ) + assert transport.last_request is not None + assert transport.last_request['method'] == 'POST' + assert urlparse(transport.last_request['url']).path == '/v3/payments/orders/ord_1/checkout' + body = json.loads(transport.last_request['body']) + assert body == { + "integrationId": "int_montonio", + "returnUrl": "https://shop.example.test/return", + "preferredCountry": "LT", + } + + +def test_async_api_payments_hit_the_routes() -> None: + seen: list[httpx.Request] = [] + + def handler(request: httpx.Request) -> httpx.Response: + seen.append(request) + return httpx.Response(200, json={"id": "ord_1"}) + + async def run() -> None: + client = AsyncNorbix( + project_id='test-project', + bearer_token='test-token', + http_client=httpx.AsyncClient(transport=httpx.MockTransport(handler)), + ) + try: + await client.api.payments.create_payment_order(buyerUserId="usr_1", currency="EUR") + await client.api.payments.get_payment_order("ord_1") + await client.api.payments.get_payment_orders(status="Paid") + await client.api.payments.start_payment_checkout("ord_1", integrationId="int_1", returnUrl="https://x.test") + finally: + await client.aclose() + + asyncio.run(run()) + assert [(r.method, urlparse(str(r.url)).path) for r in seen] == [ + ('POST', '/v3/payments/orders'), + ('GET', '/v3/payments/orders/ord_1'), + ('GET', '/v3/payments/orders'), + ('POST', '/v3/payments/orders/ord_1/checkout'), + ] diff --git a/tests/test_functions.py b/tests/test_functions.py index 1afe91b..9b215e5 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -217,6 +217,75 @@ def test_payment_fact() -> None: assert payment.received_on == "2026-10-12T08:00:00Z" +ORDER_EVENT: dict[str, Any] = { + "orderEventId": "ord_2ToIiRM03X63TZaJ2dJdv2:2", + "event": "payments.order.paid", + "from": "CheckoutStarted", + "to": "Paid", + "reason": "paid in attempt 1", + "order": { + "id": "ord_2ToIiRM03X63TZaJ2dJdv2", + "env": "PROD", + "buyerUserId": "usr_1szWVIyZFBV8HfvC4SfVw", + "merchantReference": "ad-1042-promo-1", + "currency": "EUR", + "priceVersion": "2026-10-01", + "lines": [{"sku": "star-day", "title": "Star × day", "quantity": 21, "unitAmountMinor": 30, "amountMinor": 630}], + "totalMinor": 630, + "metadata": {"adId": "ad_1042"}, + "status": "Paid", + "checkouts": [], + "settledMinor": 630, + "refundedMinor": 0, + "providerPaymentId": "mnt-1", + "mismatches": [], + }, + "payment": { + "integrationId": "int_montonio", + "provider": "Montonio", + "providerEventId": "order:mnt-1:PAID", + "orderId": "ord_2ToIiRM03X63TZaJ2dJdv2", + "eventName": "order.paid", + "status": "Succeeded", + "amountMinor": 630, + "currency": "EUR", + "receivedOn": "2026-10-19T09:54:43Z", + }, +} + + +def test_payment_order_event_and_as_payment_is_its_callback() -> None: + raw = envelope("payments", "payments.order.paid", {"order": ORDER_EVENT, "payment": ORDER_EVENT["payment"]}) + event = parse_function_event(raw) + order_event = event.as_payment_order() + assert order_event.order_event_id == "ord_2ToIiRM03X63TZaJ2dJdv2:2" + assert (order_event.event, order_event.from_, order_event.to) == ("payments.order.paid", "CheckoutStarted", "Paid") + assert order_event.reason == "paid in attempt 1" + order = order_event.order + assert order.id == "ord_2ToIiRM03X63TZaJ2dJdv2" + assert order.status == "Paid" + assert order.settled_minor == 630 + assert order.total_minor == 630 + assert order.refunded_minor == 0 + assert order.metadata == {"adId": "ad_1042"} + assert order.lines[0]["quantity"] == 21 + assert order.checkouts == [] + assert order_event.payment is not None + assert order_event.payment.provider == "Montonio" + payment = event.as_payment() + assert payment.provider_event_id == "order:mnt-1:PAID" + assert payment.order_id == "ord_2ToIiRM03X63TZaJ2dJdv2" + + +def test_as_payment_order_is_refused_for_a_plain_payment_event() -> None: + event = parse_function_event( + envelope("payments", "payments.webhook.received", {"payment": ORDER_EVENT["payment"]}) + ) + with pytest.raises(NorbixFunctionEventError) as exc: + event.as_payment_order() + assert "data.order" in str(exc.value) + + def test_ai_usage() -> None: raw = envelope("ai", "ai.credits.warning", {"ai": {"payload": {"used": 90, "limit": 100}, "targetUserId": "usr_9"}}) usage = parse_function_event(raw).as_ai_usage() diff --git a/tests/webhooks/test_receiver.py b/tests/webhooks/test_receiver.py index 8da1d96..867b75c 100644 --- a/tests/webhooks/test_receiver.py +++ b/tests/webhooks/test_receiver.py @@ -350,3 +350,82 @@ def test_payments_payload_is_the_payment_fact_with_provider_ids_on_metadata() -> assert event.metadata.payment.provider == "Stripe" # type: ignore[attr-defined] assert event.metadata.payment.provider_event_id == "evt_1" # type: ignore[attr-defined] assert "payments.webhook.received" in NORBIX_WEBHOOK_EVENT_NAMES + + +def test_payments_order_paid_hands_over_the_stored_order_and_lifts_its_ids_onto_metadata() -> None: + # gateway campaign audit/payments-checkout: a verified callback that changes a + # stored order fires payments.order.*; data is the order event, data.payment the fact. + order_event = { + "orderEventId": "ord_2ToIiRM03X63TZaJ2dJdv2:2", + "event": "payments.order.paid", + "from": "CheckoutStarted", + "to": "Paid", + "reason": "paid in attempt 1", + "order": { + "id": "ord_2ToIiRM03X63TZaJ2dJdv2", + "env": "PROD", + "buyerUserId": "usr_1szWVIyZFBV8HfvC4SfVw", + "merchantReference": "ad-1042-promo-1", + "currency": "EUR", + "priceVersion": "2026-10-01", + "lines": [{"sku": "star-day", "title": "Star × day", "quantity": 21, "unitAmountMinor": 30, "amountMinor": 630}], + "totalMinor": 630, + "metadata": {"adId": "ad_1042"}, + "status": "Paid", + "checkouts": [], + "settledMinor": 630, + "refundedMinor": 0, + "providerPaymentId": "mnt-1", + "mismatches": [], + }, + "payment": { + "integrationId": "int_montonio", + "provider": "Montonio", + "providerEventId": "order:mnt-1:PAID", + "orderId": "ord_2ToIiRM03X63TZaJ2dJdv2", + "eventName": "order.paid", + "status": "Succeeded", + "amountMinor": 630, + "currency": "EUR", + "receivedOn": "2026-10-19T09:54:43Z", + }, + } + receiver = NorbixWebhookReceiver() + captured: dict[str, object] = {} + receiver.on( + NorbixWebhookEvents.Payments.ORDER_PAID, + lambda payload, event: captured.update(payload=payload, event=event), + ) + receiver.handle(raw_body=_body("payments.order.paid", order_event, eventId="evt_order_1"), headers={}) + + payload = captured["payload"] + assert payload.order_event_id == "ord_2ToIiRM03X63TZaJ2dJdv2:2" # type: ignore[attr-defined] + assert payload.to == "Paid" # type: ignore[attr-defined] + assert payload.order.status == "Paid" # type: ignore[attr-defined] + assert payload.order.settled_minor == 630 # type: ignore[attr-defined] + assert payload.payment.provider_event_id == "order:mnt-1:PAID" # type: ignore[attr-defined] + event = captured["event"] + assert event.metadata.integration_id == "int_montonio" # type: ignore[attr-defined] + assert event.metadata.payment.provider == "Montonio" # type: ignore[attr-defined] + assert event.metadata.payment.event_name == "order.paid" # type: ignore[attr-defined] + assert event.metadata.order.id == "ord_2ToIiRM03X63TZaJ2dJdv2" # type: ignore[attr-defined] + assert event.metadata.order.order_event_id == "ord_2ToIiRM03X63TZaJ2dJdv2:2" # type: ignore[attr-defined] + assert event.metadata.order.status == "Paid" # type: ignore[attr-defined] + + +def test_every_payments_order_event_is_in_the_catalog() -> None: + names = [ + NorbixWebhookEvents.Payments.ORDER_PAID, + NorbixWebhookEvents.Payments.ORDER_PARTIALLY_REFUNDED, + NorbixWebhookEvents.Payments.ORDER_REFUNDED, + NorbixWebhookEvents.Payments.ORDER_REVERSED, + NorbixWebhookEvents.Payments.ORDER_EXPIRED, + ] + assert names == [ + "payments.order.paid", + "payments.order.partially_refunded", + "payments.order.refunded", + "payments.order.reversed", + "payments.order.expired", + ] + assert all(name in NORBIX_WEBHOOK_EVENT_NAMES for name in names)