mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(resend): expand integration with contacts, domains, and enhanced email ops (#3366)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Resend
|
||||
description: Send emails with Resend.
|
||||
description: Send emails and manage contacts with Resend.
|
||||
---
|
||||
|
||||
import { BlockInfoCard } from "@/components/ui/block-info-card"
|
||||
@@ -27,7 +27,7 @@ In Sim, the Resend integration allows your agents to programmatically send email
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Integrate Resend into the workflow. Can send emails. Requires API Key.
|
||||
Integrate Resend into your workflow. Send emails, retrieve email status, manage contacts, and view domains. Requires API Key.
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ Send an email using your own Resend API key and from address
|
||||
| `subject` | string | Yes | Email subject line |
|
||||
| `body` | string | Yes | Email body content \(plain text or HTML based on contentType\) |
|
||||
| `contentType` | string | No | Content type for the email body: "text" for plain text or "html" for HTML content |
|
||||
| `cc` | string | No | Carbon copy recipient email address |
|
||||
| `bcc` | string | No | Blind carbon copy recipient email address |
|
||||
| `replyTo` | string | No | Reply-to email address |
|
||||
| `scheduledAt` | string | No | Schedule email to be sent later in ISO 8601 format |
|
||||
| `tags` | string | No | Comma-separated key:value pairs for email tags \(e.g., "category:welcome,type:onboarding"\) |
|
||||
| `resendApiKey` | string | Yes | Resend API key for sending emails |
|
||||
|
||||
#### Output
|
||||
@@ -53,8 +58,152 @@ Send an email using your own Resend API key and from address
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Whether the email was sent successfully |
|
||||
| `id` | string | Email ID returned by Resend |
|
||||
| `to` | string | Recipient email address |
|
||||
| `subject` | string | Email subject |
|
||||
| `body` | string | Email body content |
|
||||
|
||||
### `resend_get_email`
|
||||
|
||||
Retrieve details of a previously sent email by its ID
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `emailId` | string | Yes | The ID of the email to retrieve |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | Email ID |
|
||||
| `from` | string | Sender email address |
|
||||
| `to` | json | Recipient email addresses |
|
||||
| `subject` | string | Email subject |
|
||||
| `html` | string | HTML email content |
|
||||
| `text` | string | Plain text email content |
|
||||
| `cc` | json | CC email addresses |
|
||||
| `bcc` | json | BCC email addresses |
|
||||
| `replyTo` | json | Reply-to email addresses |
|
||||
| `lastEvent` | string | Last event status \(e.g., delivered, bounced\) |
|
||||
| `createdAt` | string | Email creation timestamp |
|
||||
| `scheduledAt` | string | Scheduled send timestamp |
|
||||
| `tags` | json | Email tags as name-value pairs |
|
||||
|
||||
### `resend_create_contact`
|
||||
|
||||
Create a new contact in Resend
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `email` | string | Yes | Email address of the contact |
|
||||
| `firstName` | string | No | First name of the contact |
|
||||
| `lastName` | string | No | Last name of the contact |
|
||||
| `unsubscribed` | boolean | No | Whether the contact is unsubscribed from all broadcasts |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | Created contact ID |
|
||||
|
||||
### `resend_list_contacts`
|
||||
|
||||
List all contacts in Resend
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `contacts` | json | Array of contacts with id, email, first_name, last_name, created_at, unsubscribed |
|
||||
| `hasMore` | boolean | Whether there are more contacts to retrieve |
|
||||
|
||||
### `resend_get_contact`
|
||||
|
||||
Retrieve details of a contact by ID or email
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `contactId` | string | Yes | The contact ID or email address to retrieve |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | Contact ID |
|
||||
| `email` | string | Contact email address |
|
||||
| `firstName` | string | Contact first name |
|
||||
| `lastName` | string | Contact last name |
|
||||
| `createdAt` | string | Contact creation timestamp |
|
||||
| `unsubscribed` | boolean | Whether the contact is unsubscribed |
|
||||
|
||||
### `resend_update_contact`
|
||||
|
||||
Update an existing contact in Resend
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `contactId` | string | Yes | The contact ID or email address to update |
|
||||
| `firstName` | string | No | Updated first name |
|
||||
| `lastName` | string | No | Updated last name |
|
||||
| `unsubscribed` | boolean | No | Whether the contact should be unsubscribed from all broadcasts |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | Updated contact ID |
|
||||
|
||||
### `resend_delete_contact`
|
||||
|
||||
Delete a contact from Resend by ID or email
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `contactId` | string | Yes | The contact ID or email address to delete |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | string | Deleted contact ID |
|
||||
| `deleted` | boolean | Whether the contact was successfully deleted |
|
||||
|
||||
### `resend_list_domains`
|
||||
|
||||
List all verified domains in your Resend account
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `resendApiKey` | string | Yes | Resend API key |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `domains` | json | Array of domains with id, name, status, region, and createdAt |
|
||||
| `hasMore` | boolean | Whether there are more domains to retrieve |
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,26 @@ export const dynamic = 'force-dynamic'
|
||||
const logger = createLogger('MailSendAPI')
|
||||
|
||||
const MailSendSchema = z.object({
|
||||
fromAddress: z.string().email('Invalid from email address').min(1, 'From address is required'),
|
||||
to: z.string().email('Invalid email address').min(1, 'To email is required'),
|
||||
fromAddress: z.string().min(1, 'From address is required'),
|
||||
to: z.string().min(1, 'To email is required'),
|
||||
subject: z.string().min(1, 'Subject is required'),
|
||||
body: z.string().min(1, 'Email body is required'),
|
||||
contentType: z.enum(['text', 'html']).optional().nullable(),
|
||||
resendApiKey: z.string().min(1, 'Resend API key is required'),
|
||||
cc: z
|
||||
.union([z.string().min(1), z.array(z.string().min(1))])
|
||||
.optional()
|
||||
.nullable(),
|
||||
bcc: z
|
||||
.union([z.string().min(1), z.array(z.string().min(1))])
|
||||
.optional()
|
||||
.nullable(),
|
||||
replyTo: z
|
||||
.union([z.string().min(1), z.array(z.string().min(1))])
|
||||
.optional()
|
||||
.nullable(),
|
||||
scheduledAt: z.string().datetime().optional().nullable(),
|
||||
tags: z.string().optional().nullable(),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@@ -52,23 +66,52 @@ export async function POST(request: NextRequest) {
|
||||
const resend = new Resend(validatedData.resendApiKey)
|
||||
|
||||
const contentType = validatedData.contentType || 'text'
|
||||
const emailData =
|
||||
contentType === 'html'
|
||||
? {
|
||||
from: validatedData.fromAddress,
|
||||
to: validatedData.to,
|
||||
subject: validatedData.subject,
|
||||
html: validatedData.body,
|
||||
text: validatedData.body.replace(/<[^>]*>/g, ''), // Strip HTML for text version
|
||||
}
|
||||
: {
|
||||
from: validatedData.fromAddress,
|
||||
to: validatedData.to,
|
||||
subject: validatedData.subject,
|
||||
text: validatedData.body,
|
||||
}
|
||||
const emailData: Record<string, unknown> = {
|
||||
from: validatedData.fromAddress,
|
||||
to: validatedData.to,
|
||||
subject: validatedData.subject,
|
||||
}
|
||||
|
||||
const { data, error } = await resend.emails.send(emailData)
|
||||
if (contentType === 'html') {
|
||||
emailData.html = validatedData.body
|
||||
emailData.text = validatedData.body.replace(/<[^>]*>/g, '')
|
||||
} else {
|
||||
emailData.text = validatedData.body
|
||||
}
|
||||
|
||||
if (validatedData.cc) {
|
||||
emailData.cc = validatedData.cc
|
||||
}
|
||||
|
||||
if (validatedData.bcc) {
|
||||
emailData.bcc = validatedData.bcc
|
||||
}
|
||||
|
||||
if (validatedData.replyTo) {
|
||||
emailData.replyTo = validatedData.replyTo
|
||||
}
|
||||
|
||||
if (validatedData.scheduledAt) {
|
||||
emailData.scheduledAt = validatedData.scheduledAt
|
||||
}
|
||||
|
||||
if (validatedData.tags) {
|
||||
const tagPairs = validatedData.tags.split(',').map((pair) => {
|
||||
const trimmed = pair.trim()
|
||||
const colonIndex = trimmed.indexOf(':')
|
||||
if (colonIndex === -1) return null
|
||||
const name = trimmed.substring(0, colonIndex).trim()
|
||||
const value = trimmed.substring(colonIndex + 1).trim()
|
||||
return { name, value: value || '' }
|
||||
})
|
||||
emailData.tags = tagPairs.filter(
|
||||
(tag): tag is { name: string; value: string } => tag !== null && !!tag.name
|
||||
)
|
||||
}
|
||||
|
||||
const { data, error } = await resend.emails.send(
|
||||
emailData as unknown as Parameters<typeof resend.emails.send>[0]
|
||||
)
|
||||
|
||||
if (error) {
|
||||
logger.error(`[${requestId}] Email sending failed:`, error)
|
||||
|
||||
@@ -1,23 +1,53 @@
|
||||
import { ResendIcon } from '@/components/icons'
|
||||
import type { BlockConfig } from '@/blocks/types'
|
||||
import type { MailSendResult } from '@/tools/resend/types'
|
||||
|
||||
export const ResendBlock: BlockConfig<MailSendResult> = {
|
||||
export const ResendBlock: BlockConfig = {
|
||||
type: 'resend',
|
||||
name: 'Resend',
|
||||
description: 'Send emails with Resend.',
|
||||
longDescription: 'Integrate Resend into the workflow. Can send emails. Requires API Key.',
|
||||
description: 'Send emails and manage contacts with Resend.',
|
||||
longDescription:
|
||||
'Integrate Resend into your workflow. Send emails, retrieve email status, manage contacts, and view domains. Requires API Key.',
|
||||
docsLink: 'https://docs.sim.ai/tools/resend',
|
||||
category: 'tools',
|
||||
bgColor: '#181C1E',
|
||||
icon: ResendIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
// Email Operations
|
||||
{ label: 'Send Email', id: 'send_email' },
|
||||
{ label: 'Get Email', id: 'get_email' },
|
||||
// Contact Operations
|
||||
{ label: 'Create Contact', id: 'create_contact' },
|
||||
{ label: 'List Contacts', id: 'list_contacts' },
|
||||
{ label: 'Get Contact', id: 'get_contact' },
|
||||
{ label: 'Update Contact', id: 'update_contact' },
|
||||
{ label: 'Delete Contact', id: 'delete_contact' },
|
||||
// Domain Operations
|
||||
{ label: 'List Domains', id: 'list_domains' },
|
||||
],
|
||||
value: () => 'send_email',
|
||||
},
|
||||
{
|
||||
id: 'resendApiKey',
|
||||
title: 'Resend API Key',
|
||||
type: 'short-input',
|
||||
placeholder: 'Your Resend API key',
|
||||
required: true,
|
||||
password: true,
|
||||
},
|
||||
|
||||
// Send Email fields
|
||||
{
|
||||
id: 'fromAddress',
|
||||
title: 'From Address',
|
||||
type: 'short-input',
|
||||
placeholder: 'sender@yourdomain.com',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -25,6 +55,7 @@ export const ResendBlock: BlockConfig<MailSendResult> = {
|
||||
title: 'To',
|
||||
type: 'short-input',
|
||||
placeholder: 'recipient@example.com',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -32,14 +63,46 @@ export const ResendBlock: BlockConfig<MailSendResult> = {
|
||||
title: 'Subject',
|
||||
type: 'short-input',
|
||||
placeholder: 'Email subject',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
required: true,
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
prompt: `Generate a compelling email subject line based on the user's description.
|
||||
|
||||
### GUIDELINES
|
||||
- Keep it concise (50 characters or less is ideal)
|
||||
- Make it attention-grabbing
|
||||
- Avoid spam trigger words
|
||||
- Be clear about the email content
|
||||
|
||||
### EXAMPLES
|
||||
"Welcome email for new users" -> "Welcome to Our Platform!"
|
||||
"Order confirmation" -> "Your Order #12345 is Confirmed"
|
||||
"Newsletter about new features" -> "New Features You'll Love"
|
||||
|
||||
Return ONLY the subject line - no explanations.`,
|
||||
placeholder: 'Describe the email topic...',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'body',
|
||||
title: 'Body',
|
||||
type: 'long-input',
|
||||
placeholder: 'Email body content',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
required: true,
|
||||
wandConfig: {
|
||||
enabled: true,
|
||||
prompt: `Generate email content based on the user's description.
|
||||
|
||||
### GUIDELINES
|
||||
- Use clear, readable formatting
|
||||
- Keep paragraphs short
|
||||
- Include appropriate greeting and sign-off
|
||||
|
||||
Return ONLY the email body - no explanations.`,
|
||||
placeholder: 'Describe the email content...',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'contentType',
|
||||
@@ -50,45 +113,175 @@ export const ResendBlock: BlockConfig<MailSendResult> = {
|
||||
{ label: 'HTML', id: 'html' },
|
||||
],
|
||||
value: () => 'text',
|
||||
required: false,
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
{
|
||||
id: 'resendApiKey',
|
||||
title: 'Resend API Key',
|
||||
id: 'cc',
|
||||
title: 'CC',
|
||||
type: 'short-input',
|
||||
placeholder: 'Your Resend API key',
|
||||
placeholder: 'cc@example.com',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
{
|
||||
id: 'bcc',
|
||||
title: 'BCC',
|
||||
type: 'short-input',
|
||||
placeholder: 'bcc@example.com',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
{
|
||||
id: 'replyTo',
|
||||
title: 'Reply To',
|
||||
type: 'short-input',
|
||||
placeholder: 'reply@example.com',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
{
|
||||
id: 'scheduledAt',
|
||||
title: 'Schedule At',
|
||||
type: 'short-input',
|
||||
placeholder: '2024-08-05T11:52:01.858Z',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
{
|
||||
id: 'tags',
|
||||
title: 'Tags',
|
||||
type: 'short-input',
|
||||
placeholder: 'category:welcome,type:onboarding',
|
||||
condition: { field: 'operation', value: 'send_email' },
|
||||
},
|
||||
|
||||
// Get Email fields
|
||||
{
|
||||
id: 'emailId',
|
||||
title: 'Email ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Email ID to retrieve',
|
||||
condition: { field: 'operation', value: 'get_email' },
|
||||
required: true,
|
||||
},
|
||||
|
||||
// Create Contact fields
|
||||
{
|
||||
id: 'email',
|
||||
title: 'Email',
|
||||
type: 'short-input',
|
||||
placeholder: 'contact@example.com',
|
||||
condition: { field: 'operation', value: 'create_contact' },
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'firstName',
|
||||
title: 'First Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'John',
|
||||
condition: { field: 'operation', value: ['create_contact', 'update_contact'] },
|
||||
},
|
||||
{
|
||||
id: 'lastName',
|
||||
title: 'Last Name',
|
||||
type: 'short-input',
|
||||
placeholder: 'Doe',
|
||||
condition: { field: 'operation', value: ['create_contact', 'update_contact'] },
|
||||
},
|
||||
{
|
||||
id: 'unsubscribed',
|
||||
title: 'Unsubscribed',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'No', id: 'false' },
|
||||
{ label: 'Yes', id: 'true' },
|
||||
],
|
||||
value: () => 'false',
|
||||
condition: { field: 'operation', value: ['create_contact', 'update_contact'] },
|
||||
},
|
||||
|
||||
// Get/Update/Delete Contact fields
|
||||
{
|
||||
id: 'contactId',
|
||||
title: 'Contact ID or Email',
|
||||
type: 'short-input',
|
||||
placeholder: 'Contact ID or email address',
|
||||
condition: { field: 'operation', value: ['get_contact', 'update_contact', 'delete_contact'] },
|
||||
required: true,
|
||||
password: true,
|
||||
},
|
||||
],
|
||||
|
||||
tools: {
|
||||
access: ['resend_send'],
|
||||
access: [
|
||||
'resend_send',
|
||||
'resend_get_email',
|
||||
'resend_create_contact',
|
||||
'resend_list_contacts',
|
||||
'resend_get_contact',
|
||||
'resend_update_contact',
|
||||
'resend_delete_contact',
|
||||
'resend_list_domains',
|
||||
],
|
||||
config: {
|
||||
tool: () => 'resend_send',
|
||||
params: (params) => ({
|
||||
resendApiKey: params.resendApiKey,
|
||||
fromAddress: params.fromAddress,
|
||||
to: params.to,
|
||||
subject: params.subject,
|
||||
body: params.body,
|
||||
}),
|
||||
tool: (params) => {
|
||||
const operation = params.operation || 'send_email'
|
||||
if (operation === 'send_email') return 'resend_send'
|
||||
return `resend_${operation}`
|
||||
},
|
||||
params: (params) => {
|
||||
const { operation, ...rest } = params
|
||||
|
||||
if (rest.unsubscribed !== undefined) {
|
||||
rest.unsubscribed = rest.unsubscribed === 'true'
|
||||
}
|
||||
|
||||
return rest
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
resendApiKey: { type: 'string', description: 'Resend API key' },
|
||||
// Send email inputs
|
||||
fromAddress: { type: 'string', description: 'Email address to send from' },
|
||||
to: { type: 'string', description: 'Recipient email address' },
|
||||
subject: { type: 'string', description: 'Email subject' },
|
||||
body: { type: 'string', description: 'Email body content' },
|
||||
contentType: { type: 'string', description: 'Content type (text or html)' },
|
||||
resendApiKey: { type: 'string', description: 'Resend API key for sending emails' },
|
||||
cc: { type: 'string', description: 'CC email address' },
|
||||
bcc: { type: 'string', description: 'BCC email address' },
|
||||
replyTo: { type: 'string', description: 'Reply-to email address' },
|
||||
scheduledAt: { type: 'string', description: 'Scheduled send time in ISO 8601 format' },
|
||||
tags: { type: 'string', description: 'Email tags as key:value pairs' },
|
||||
// Get email inputs
|
||||
emailId: { type: 'string', description: 'Email ID to retrieve' },
|
||||
// Contact inputs
|
||||
email: { type: 'string', description: 'Contact email address' },
|
||||
firstName: { type: 'string', description: 'Contact first name' },
|
||||
lastName: { type: 'string', description: 'Contact last name' },
|
||||
unsubscribed: { type: 'string', description: 'Contact subscription status' },
|
||||
contactId: { type: 'string', description: 'Contact ID or email address' },
|
||||
},
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the email was sent successfully' },
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
// Send email outputs
|
||||
to: { type: 'string', description: 'Recipient email address' },
|
||||
subject: { type: 'string', description: 'Email subject' },
|
||||
body: { type: 'string', description: 'Email body content' },
|
||||
// Get email outputs
|
||||
id: { type: 'string', description: 'Email or contact ID' },
|
||||
from: { type: 'string', description: 'Sender email address' },
|
||||
html: { type: 'string', description: 'HTML email content' },
|
||||
text: { type: 'string', description: 'Plain text email content' },
|
||||
lastEvent: { type: 'string', description: 'Last event status' },
|
||||
createdAt: { type: 'string', description: 'Creation timestamp' },
|
||||
tags: { type: 'json', description: 'Email tags as name-value pairs' },
|
||||
// Contact outputs
|
||||
email: { type: 'string', description: 'Contact email address' },
|
||||
firstName: { type: 'string', description: 'Contact first name' },
|
||||
lastName: { type: 'string', description: 'Contact last name' },
|
||||
contacts: { type: 'json', description: 'Array of contacts' },
|
||||
// Domain outputs
|
||||
domains: { type: 'json', description: 'Array of domains' },
|
||||
hasMore: { type: 'boolean', description: 'Whether more results are available' },
|
||||
deleted: { type: 'boolean', description: 'Whether the resource was deleted' },
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1590,7 +1590,16 @@ import {
|
||||
redisTtlTool,
|
||||
} from '@/tools/redis'
|
||||
import { reductoParserTool, reductoParserV2Tool } from '@/tools/reducto'
|
||||
import { mailSendTool } from '@/tools/resend'
|
||||
import {
|
||||
mailSendTool,
|
||||
resendCreateContactTool,
|
||||
resendDeleteContactTool,
|
||||
resendGetContactTool,
|
||||
resendGetEmailTool,
|
||||
resendListContactsTool,
|
||||
resendListDomainsTool,
|
||||
resendUpdateContactTool,
|
||||
} from '@/tools/resend'
|
||||
import {
|
||||
revenuecatCreatePurchaseTool,
|
||||
revenuecatDeferGoogleSubscriptionTool,
|
||||
@@ -2341,6 +2350,13 @@ export const tools: Record<string, ToolConfig> = {
|
||||
linkedin_share_post: linkedInSharePostTool,
|
||||
linkedin_get_profile: linkedInGetProfileTool,
|
||||
resend_send: mailSendTool,
|
||||
resend_get_email: resendGetEmailTool,
|
||||
resend_create_contact: resendCreateContactTool,
|
||||
resend_list_contacts: resendListContactsTool,
|
||||
resend_get_contact: resendGetContactTool,
|
||||
resend_update_contact: resendUpdateContactTool,
|
||||
resend_delete_contact: resendDeleteContactTool,
|
||||
resend_list_domains: resendListDomainsTool,
|
||||
sendgrid_send_mail: sendGridSendMailTool,
|
||||
sendgrid_add_contact: sendGridAddContactTool,
|
||||
sendgrid_get_contact: sendGridGetContactTool,
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { CreateContactParams, CreateContactResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendCreateContactTool: ToolConfig<CreateContactParams, CreateContactResult> = {
|
||||
id: 'resend_create_contact',
|
||||
name: 'Create Contact',
|
||||
description: 'Create a new contact in Resend',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
email: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Email address of the contact',
|
||||
},
|
||||
firstName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'First name of the contact',
|
||||
},
|
||||
lastName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Last name of the contact',
|
||||
},
|
||||
unsubscribed: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the contact is unsubscribed from all broadcasts',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.resend.com/contacts',
|
||||
method: 'POST',
|
||||
headers: (params: CreateContactParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: CreateContactParams) => ({
|
||||
email: params.email,
|
||||
...(params.firstName && { first_name: params.firstName }),
|
||||
...(params.lastName && { last_name: params.lastName }),
|
||||
...(params.unsubscribed !== undefined && { unsubscribed: params.unsubscribed }),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<CreateContactResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Created contact ID' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { DeleteContactParams, DeleteContactResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendDeleteContactTool: ToolConfig<DeleteContactParams, DeleteContactResult> = {
|
||||
id: 'resend_delete_contact',
|
||||
name: 'Delete Contact',
|
||||
description: 'Delete a contact from Resend by ID or email',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The contact ID or email address to delete',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: DeleteContactParams) =>
|
||||
`https://api.resend.com/contacts/${encodeURIComponent(params.contactId)}`,
|
||||
method: 'DELETE',
|
||||
headers: (params: DeleteContactParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<DeleteContactResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.contact || data.id || '',
|
||||
deleted: data.deleted ?? true,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Deleted contact ID' },
|
||||
deleted: { type: 'boolean', description: 'Whether the contact was successfully deleted' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { GetContactParams, GetContactResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendGetContactTool: ToolConfig<GetContactParams, GetContactResult> = {
|
||||
id: 'resend_get_contact',
|
||||
name: 'Get Contact',
|
||||
description: 'Retrieve details of a contact by ID or email',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The contact ID or email address to retrieve',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: GetContactParams) =>
|
||||
`https://api.resend.com/contacts/${encodeURIComponent(params.contactId)}`,
|
||||
method: 'GET',
|
||||
headers: (params: GetContactParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<GetContactResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
email: data.email,
|
||||
firstName: data.first_name || '',
|
||||
lastName: data.last_name || '',
|
||||
createdAt: data.created_at || '',
|
||||
unsubscribed: data.unsubscribed || false,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Contact ID' },
|
||||
email: { type: 'string', description: 'Contact email address' },
|
||||
firstName: { type: 'string', description: 'Contact first name' },
|
||||
lastName: { type: 'string', description: 'Contact last name' },
|
||||
createdAt: { type: 'string', description: 'Contact creation timestamp' },
|
||||
unsubscribed: { type: 'boolean', description: 'Whether the contact is unsubscribed' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { GetEmailParams, GetEmailResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendGetEmailTool: ToolConfig<GetEmailParams, GetEmailResult> = {
|
||||
id: 'resend_get_email',
|
||||
name: 'Get Email',
|
||||
description: 'Retrieve details of a previously sent email by its ID',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
emailId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the email to retrieve',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: GetEmailParams) => `https://api.resend.com/emails/${params.emailId}`,
|
||||
method: 'GET',
|
||||
headers: (params: GetEmailParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<GetEmailResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
from: data.from,
|
||||
to: data.to || [],
|
||||
subject: data.subject,
|
||||
html: data.html || '',
|
||||
text: data.text || null,
|
||||
cc: data.cc || [],
|
||||
bcc: data.bcc || [],
|
||||
replyTo: data.reply_to || [],
|
||||
lastEvent: data.last_event || '',
|
||||
createdAt: data.created_at || '',
|
||||
scheduledAt: data.scheduled_at || null,
|
||||
tags: data.tags || [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Email ID' },
|
||||
from: { type: 'string', description: 'Sender email address' },
|
||||
to: { type: 'json', description: 'Recipient email addresses' },
|
||||
subject: { type: 'string', description: 'Email subject' },
|
||||
html: { type: 'string', description: 'HTML email content' },
|
||||
text: { type: 'string', description: 'Plain text email content' },
|
||||
cc: { type: 'json', description: 'CC email addresses' },
|
||||
bcc: { type: 'json', description: 'BCC email addresses' },
|
||||
replyTo: { type: 'json', description: 'Reply-to email addresses' },
|
||||
lastEvent: { type: 'string', description: 'Last event status (e.g., delivered, bounced)' },
|
||||
createdAt: { type: 'string', description: 'Email creation timestamp' },
|
||||
scheduledAt: { type: 'string', description: 'Scheduled send timestamp' },
|
||||
tags: { type: 'json', description: 'Email tags as name-value pairs' },
|
||||
},
|
||||
}
|
||||
@@ -1,3 +1,26 @@
|
||||
import { mailSendTool } from '@/tools/resend/send'
|
||||
|
||||
export { mailSendTool }
|
||||
export { resendCreateContactTool } from '@/tools/resend/create_contact'
|
||||
export { resendDeleteContactTool } from '@/tools/resend/delete_contact'
|
||||
export { resendGetContactTool } from '@/tools/resend/get_contact'
|
||||
export { resendGetEmailTool } from '@/tools/resend/get_email'
|
||||
export { resendListContactsTool } from '@/tools/resend/list_contacts'
|
||||
export { resendListDomainsTool } from '@/tools/resend/list_domains'
|
||||
export { mailSendTool } from '@/tools/resend/send'
|
||||
export type {
|
||||
CreateContactParams,
|
||||
CreateContactResult,
|
||||
DeleteContactParams,
|
||||
DeleteContactResult,
|
||||
GetContactParams,
|
||||
GetContactResult,
|
||||
GetEmailParams,
|
||||
GetEmailResult,
|
||||
ListContactsParams,
|
||||
ListContactsResult,
|
||||
ListDomainsParams,
|
||||
ListDomainsResult,
|
||||
MailSendParams,
|
||||
MailSendResult,
|
||||
UpdateContactParams,
|
||||
UpdateContactResult,
|
||||
} from '@/tools/resend/types'
|
||||
export { resendUpdateContactTool } from '@/tools/resend/update_contact'
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { ListContactsParams, ListContactsResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendListContactsTool: ToolConfig<ListContactsParams, ListContactsResult> = {
|
||||
id: 'resend_list_contacts',
|
||||
name: 'List Contacts',
|
||||
description: 'List all contacts in Resend',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.resend.com/contacts',
|
||||
method: 'GET',
|
||||
headers: (params: ListContactsParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ListContactsResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
contacts: data.data || [],
|
||||
hasMore: data.has_more || false,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
contacts: {
|
||||
type: 'json',
|
||||
description:
|
||||
'Array of contacts with id, email, first_name, last_name, created_at, unsubscribed',
|
||||
},
|
||||
hasMore: { type: 'boolean', description: 'Whether there are more contacts to retrieve' },
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { ListDomainsParams, ListDomainsResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendListDomainsTool: ToolConfig<ListDomainsParams, ListDomainsResult> = {
|
||||
id: 'resend_list_domains',
|
||||
name: 'List Domains',
|
||||
description: 'List all verified domains in your Resend account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: 'https://api.resend.com/domains',
|
||||
method: 'GET',
|
||||
headers: (params: ListDomainsParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<ListDomainsResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
domains: (data.data || []).map(
|
||||
(domain: {
|
||||
id: string
|
||||
name: string
|
||||
status: string
|
||||
region: string
|
||||
created_at: string
|
||||
}) => ({
|
||||
id: domain.id,
|
||||
name: domain.name,
|
||||
status: domain.status,
|
||||
region: domain.region,
|
||||
createdAt: domain.created_at,
|
||||
})
|
||||
),
|
||||
hasMore: data.has_more || false,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
domains: {
|
||||
type: 'json',
|
||||
description: 'Array of domains with id, name, status, region, and createdAt',
|
||||
},
|
||||
hasMore: { type: 'boolean', description: 'Whether there are more domains to retrieve' },
|
||||
},
|
||||
}
|
||||
@@ -41,6 +41,37 @@ export const mailSendTool: ToolConfig<MailSendParams, MailSendResult> = {
|
||||
description:
|
||||
'Content type for the email body: "text" for plain text or "html" for HTML content',
|
||||
},
|
||||
cc: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Carbon copy recipient email address',
|
||||
},
|
||||
bcc: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Blind carbon copy recipient email address',
|
||||
},
|
||||
replyTo: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Reply-to email address',
|
||||
},
|
||||
scheduledAt: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Schedule email to be sent later in ISO 8601 format',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Comma-separated key:value pairs for email tags (e.g., "category:welcome,type:onboarding")',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
@@ -62,6 +93,11 @@ export const mailSendTool: ToolConfig<MailSendParams, MailSendResult> = {
|
||||
subject: params.subject,
|
||||
body: params.body,
|
||||
contentType: params.contentType || 'text',
|
||||
...(params.cc && { cc: params.cc }),
|
||||
...(params.bcc && { bcc: params.bcc }),
|
||||
...(params.replyTo && { replyTo: params.replyTo }),
|
||||
...(params.scheduledAt && { scheduledAt: params.scheduledAt }),
|
||||
...(params.tags && { tags: params.tags }),
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -72,6 +108,7 @@ export const mailSendTool: ToolConfig<MailSendParams, MailSendResult> = {
|
||||
success: true,
|
||||
output: {
|
||||
success: result.success,
|
||||
id: result.data?.id || '',
|
||||
to: params?.to || '',
|
||||
subject: params?.subject || '',
|
||||
body: params?.body || '',
|
||||
@@ -81,6 +118,7 @@ export const mailSendTool: ToolConfig<MailSendParams, MailSendResult> = {
|
||||
|
||||
outputs: {
|
||||
success: { type: 'boolean', description: 'Whether the email was sent successfully' },
|
||||
id: { type: 'string', description: 'Email ID returned by Resend' },
|
||||
to: { type: 'string', description: 'Recipient email address' },
|
||||
subject: { type: 'string', description: 'Email subject' },
|
||||
body: { type: 'string', description: 'Email body content' },
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
/** Send Email */
|
||||
export interface MailSendParams {
|
||||
resendApiKey: string
|
||||
fromAddress: string
|
||||
@@ -7,13 +8,140 @@ export interface MailSendParams {
|
||||
subject: string
|
||||
body: string
|
||||
contentType?: 'text' | 'html'
|
||||
cc?: string
|
||||
bcc?: string
|
||||
replyTo?: string
|
||||
scheduledAt?: string
|
||||
tags?: string
|
||||
}
|
||||
|
||||
export interface MailSendResult extends ToolResponse {
|
||||
output: {
|
||||
success: boolean
|
||||
id: string
|
||||
to: string
|
||||
subject: string
|
||||
body: string
|
||||
}
|
||||
}
|
||||
|
||||
/** Get Email */
|
||||
export interface GetEmailParams {
|
||||
resendApiKey: string
|
||||
emailId: string
|
||||
}
|
||||
|
||||
export interface GetEmailResult extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
from: string
|
||||
to: string[]
|
||||
subject: string
|
||||
html: string
|
||||
text: string | null
|
||||
cc: string[]
|
||||
bcc: string[]
|
||||
replyTo: string[]
|
||||
lastEvent: string
|
||||
createdAt: string
|
||||
scheduledAt: string | null
|
||||
tags: Array<{ name: string; value: string }>
|
||||
}
|
||||
}
|
||||
|
||||
/** Create Contact */
|
||||
export interface CreateContactParams {
|
||||
resendApiKey: string
|
||||
email: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
unsubscribed?: boolean
|
||||
}
|
||||
|
||||
export interface CreateContactResult extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
/** List Contacts */
|
||||
export interface ListContactsParams {
|
||||
resendApiKey: string
|
||||
}
|
||||
|
||||
export interface ListContactsResult extends ToolResponse {
|
||||
output: {
|
||||
contacts: Array<{
|
||||
id: string
|
||||
email: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
created_at: string
|
||||
unsubscribed: boolean
|
||||
}>
|
||||
hasMore: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** Get Contact */
|
||||
export interface GetContactParams {
|
||||
resendApiKey: string
|
||||
contactId: string
|
||||
}
|
||||
|
||||
export interface GetContactResult extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
email: string
|
||||
firstName: string
|
||||
lastName: string
|
||||
createdAt: string
|
||||
unsubscribed: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** Update Contact */
|
||||
export interface UpdateContactParams {
|
||||
resendApiKey: string
|
||||
contactId: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
unsubscribed?: boolean
|
||||
}
|
||||
|
||||
export interface UpdateContactResult extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
}
|
||||
}
|
||||
|
||||
/** Delete Contact */
|
||||
export interface DeleteContactParams {
|
||||
resendApiKey: string
|
||||
contactId: string
|
||||
}
|
||||
|
||||
export interface DeleteContactResult extends ToolResponse {
|
||||
output: {
|
||||
id: string
|
||||
deleted: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** List Domains */
|
||||
export interface ListDomainsParams {
|
||||
resendApiKey: string
|
||||
}
|
||||
|
||||
export interface ListDomainsResult extends ToolResponse {
|
||||
output: {
|
||||
domains: Array<{
|
||||
id: string
|
||||
name: string
|
||||
status: string
|
||||
region: string
|
||||
createdAt: string
|
||||
}>
|
||||
hasMore: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import type { UpdateContactParams, UpdateContactResult } from '@/tools/resend/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resendUpdateContactTool: ToolConfig<UpdateContactParams, UpdateContactResult> = {
|
||||
id: 'resend_update_contact',
|
||||
name: 'Update Contact',
|
||||
description: 'Update an existing contact in Resend',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
contactId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The contact ID or email address to update',
|
||||
},
|
||||
firstName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Updated first name',
|
||||
},
|
||||
lastName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Updated last name',
|
||||
},
|
||||
unsubscribed: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether the contact should be unsubscribed from all broadcasts',
|
||||
},
|
||||
resendApiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Resend API key',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: UpdateContactParams) =>
|
||||
`https://api.resend.com/contacts/${encodeURIComponent(params.contactId)}`,
|
||||
method: 'PATCH',
|
||||
headers: (params: UpdateContactParams) => ({
|
||||
Authorization: `Bearer ${params.resendApiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params: UpdateContactParams) => ({
|
||||
...(params.firstName !== undefined && { first_name: params.firstName }),
|
||||
...(params.lastName !== undefined && { last_name: params.lastName }),
|
||||
...(params.unsubscribed !== undefined && { unsubscribed: params.unsubscribed }),
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response): Promise<UpdateContactResult> => {
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: { type: 'string', description: 'Updated contact ID' },
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user