diff --git a/README.md b/README.md index 481c0d54a..4510ddca3 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ This library currently supports a subset of the [Braze API endpoints](https://ww - [x] /canvas/trigger/schedule/create - [x] /canvas/trigger/schedule/delete - [x] /canvas/trigger/schedule/update -- [ ] /messages/schedule/create +- [x] /messages/schedule/create - [ ] /messages/schedule/delete - [ ] /messages/schedule/update - [ ] /messages/scheduled_broadcasts diff --git a/src/Braze.test.ts b/src/Braze.test.ts index 2a71aa306..c6607e7a4 100644 --- a/src/Braze.test.ts +++ b/src/Braze.test.ts @@ -7,6 +7,7 @@ import type { CanvasTriggerScheduleDeleteObject, CanvasTriggerScheduleUpdateObject, CanvasTriggerSendObject, + MessagesScheduleCreateObject, MessagesSendObject, SendsIdCreateObject, TransactionalV1CampaignsSendObject, @@ -134,6 +135,13 @@ it('calls canvas.trigger.send()', async () => { expect(mockedRequest).toBeCalledTimes(1) }) +it('calls messages.schedule.create()', async () => { + mockedRequest.mockResolvedValueOnce(response) + expect(await braze.messages.schedule.create(body as MessagesScheduleCreateObject)).toBe(response) + expect(mockedRequest).toBeCalledWith(`${apiUrl}/messages/schedule/create`, body, options) + expect(mockedRequest).toBeCalledTimes(1) +}) + it('calls messages.send()', async () => { mockedRequest.mockResolvedValueOnce(response) expect(await braze.messages.send(body as MessagesSendObject)).toBe(response) diff --git a/src/Braze.ts b/src/Braze.ts index 57cc42fd9..f82f58235 100644 --- a/src/Braze.ts +++ b/src/Braze.ts @@ -70,6 +70,11 @@ export class Braze { } messages = { + schedule: { + create: (body: messages.schedule.MessagesScheduleCreateObject) => + messages.schedule.create(this.apiUrl, this.apiKey, body), + }, + send: (body: messages.MessagesSendObject) => messages.send(this.apiUrl, this.apiKey, body), } diff --git a/src/index.ts b/src/index.ts index 6ebed44b3..5e734ed11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ export * from './campaigns/trigger/types' export * from './canvas/trigger/schedule/types' export * from './canvas/trigger/types' export * from './common/types' +export * from './messages/schedule/types' export * from './messages/types' export * from './sends/id/types' export * from './transactional/v1/campaigns/types' diff --git a/src/messages/index.ts b/src/messages/index.ts index 9ae72aae4..34e08645c 100644 --- a/src/messages/index.ts +++ b/src/messages/index.ts @@ -1,2 +1,3 @@ +export * as schedule from './schedule' export * from './send' export * from './types' diff --git a/src/messages/schedule/create.test.ts b/src/messages/schedule/create.test.ts new file mode 100644 index 000000000..de4e59129 --- /dev/null +++ b/src/messages/schedule/create.test.ts @@ -0,0 +1,98 @@ +import { post } from '../../common/request' +import { create } from '.' +import type { MessagesScheduleCreateObject } from './types' + +jest.mock('../../common/request') +const mockedPost = jest.mocked(post) + +beforeEach(() => { + jest.clearAllMocks() +}) + +describe('/messages/schedule/create', () => { + const apiUrl = 'https://rest.iad-01.braze.com' + const apiKey = 'apiKey' + + const body: MessagesScheduleCreateObject = { + broadcast: false, + external_user_ids: ['external_user_identifiers'], + user_aliases: [ + { + alias_name: 'example_name', + alias_label: 'example_label', + }, + ], + segment_id: 'segment_identifiers', + audience: { + AND: [ + { + custom_attribute: { + custom_attribute_name: 'eye_color', + comparison: 'equals', + value: 'blue', + }, + }, + { + custom_attribute: { + custom_attribute_name: 'favorite_foods', + comparison: 'includes_value', + value: 'pizza', + }, + }, + { + OR: [ + { + custom_attribute: { + custom_attribute_name: 'last_purchase_time', + comparison: 'less_than_x_days_ago', + value: 2, + }, + }, + { + push_subscription_status: { + comparison: 'is', + value: 'opted_in', + }, + }, + ], + }, + { + email_subscription_status: { + comparison: 'is_not', + value: 'subscribed', + }, + }, + { + last_used_app: { + comparison: 'after', + value: '2019-07-22T13:17:55+0000', + }, + }, + ], + }, + campaign_id: 'campaign_identifier', + send_id: 'send_identifier', + override_messaging_limits: false, + recipient_subscription_state: 'subscribed', + schedule: { + time: '', + in_local_time: true, + at_optimal_time: true, + }, + messages: {}, + } + + const data = {} + + it('calls request with url and body', async () => { + mockedPost.mockResolvedValueOnce(data) + expect(await create(apiUrl, apiKey, body)).toBe(data) + expect(mockedPost).toBeCalledWith(`${apiUrl}/messages/schedule/create`, body, { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${apiKey}`, + }, + }) + expect(mockedPost).toBeCalledTimes(1) + }) +}) diff --git a/src/messages/schedule/create.ts b/src/messages/schedule/create.ts new file mode 100644 index 000000000..9a6cf0e49 --- /dev/null +++ b/src/messages/schedule/create.ts @@ -0,0 +1,29 @@ +import { post } from '../../common/request' +import type { MessagesScheduleCreateObject } from './types' + +/** + * Create scheduled messages. + * + * Use this endpoint to send messages directly from the API. + * + * {@link https://www.braze.com/docs/api/endpoints/messaging/schedule_messages/post_schedule_messages/} + * + * @param apiUrl - Braze REST endpoint. + * @param apiKey - Braze API key. + * @param body - Request parameters. + * @returns - Braze response. + */ +export function create(apiUrl: string, apiKey: string, body: MessagesScheduleCreateObject) { + const options = { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${apiKey}`, + }, + } + + return post(`${apiUrl}/messages/schedule/create`, body, options) as Promise<{ + dispatch_id: string + schedule_id: string + message: 'success' | string + }> +} diff --git a/src/messages/schedule/index.ts b/src/messages/schedule/index.ts new file mode 100644 index 000000000..e94961485 --- /dev/null +++ b/src/messages/schedule/index.ts @@ -0,0 +1,2 @@ +export * from './create' +export * from './types' diff --git a/src/messages/schedule/types.ts b/src/messages/schedule/types.ts new file mode 100644 index 000000000..2c7119269 --- /dev/null +++ b/src/messages/schedule/types.ts @@ -0,0 +1,13 @@ +import type { ScheduleObject } from '../../common/types' +import type { MessagesSendObject } from '../types' + +/** + * Request body for create scheduled messages. + * + * {@link https://www.braze.com/docs/api/endpoints/messaging/schedule_messages/post_schedule_messages/#request-body} + */ +export interface MessagesScheduleCreateObject + extends Omit { + override_messaging_limits?: boolean + schedule: ScheduleObject +} diff --git a/src/messages/types.ts b/src/messages/types.ts index 4eb9ed138..1dae6dec1 100644 --- a/src/messages/types.ts +++ b/src/messages/types.ts @@ -1,4 +1,4 @@ -import type { ConnectedAudienceObject } from '../common/types' +import type { ConnectedAudienceObject, UserAlias } from '../common/types' /** * Request body for sending messages immediately via API only. @@ -8,10 +8,7 @@ import type { ConnectedAudienceObject } from '../common/types' export interface MessagesSendObject { broadcast?: boolean external_user_ids?: string[] - user_aliases?: { - alias_name: string - alias_label: string - }[] + user_aliases?: UserAlias[] segment_id?: string audience?: ConnectedAudienceObject campaign_id?: string