{"id":50140473,"url":"https://github.com/humanlayer/pulumi-resend","last_synced_at":"2026-05-24T01:02:57.114Z","repository":{"id":359677085,"uuid":"1244998631","full_name":"humanlayer/pulumi-resend","owner":"humanlayer","description":"Pulumi Provider for Resend API","archived":false,"fork":false,"pushed_at":"2026-05-22T21:55:11.000Z","size":114,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T23:40:21.508Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/humanlayer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T20:08:40.000Z","updated_at":"2026-05-22T21:55:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/humanlayer/pulumi-resend","commit_stats":null,"previous_names":["humanlayer/pulumi-resend"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/humanlayer/pulumi-resend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanlayer%2Fpulumi-resend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanlayer%2Fpulumi-resend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanlayer%2Fpulumi-resend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanlayer%2Fpulumi-resend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/humanlayer","download_url":"https://codeload.github.com/humanlayer/pulumi-resend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanlayer%2Fpulumi-resend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33417490,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T22:14:44.296Z","status":"ssl_error","status_checked_at":"2026-05-23T22:14:43.778Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-24T01:02:52.904Z","updated_at":"2026-05-24T01:02:57.081Z","avatar_url":"https://github.com/humanlayer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pulumi Resend Provider\n\nA native Pulumi provider for managing [Resend](https://resend.com) email infrastructure as code.\n\n## Installation\n\n### TypeScript/JavaScript\n\n```bash\nnpm install @humanlayer/pulumi-resend\n```\n\n### Provider Binary\n\nThe provider binary is automatically downloaded from GitHub releases when you run `pulumi up`.\n\n## Configuration\n\nSet your Resend API key via environment variable or Pulumi config:\n\n```bash\nexport RESEND_API_KEY=re_xxxxx\n# or\npulumi config set resend:apiKey re_xxxxx --secret\n```\n\n## Usage\n\n### Domain\n\nCreate and manage email sending domains:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst domain = new resend.Domain(\"my-domain\", {\n    name: \"mail.example.com\",\n    region: \"us-east-1\",\n});\n\nexport const domainId = domain.id;\nexport const dnsRecords = domain.records;\n```\n\n### Domain Verification\n\nTrigger DNS verification for a domain:\n\n```typescript\nconst verification = new resend.DomainVerification(\"verify\", {\n    domainId: domain.id,\n});\n\nexport const verificationStatus = verification.status;\n```\n\n### API Key\n\nCreate API keys for sending emails:\n\n```typescript\nconst apiKey = new resend.ApiKey(\"sending-key\", {\n    name: \"production-sender\",\n    permission: \"sending_access\",\n});\n\nexport const keyId = apiKey.id;\nexport const token = apiKey.token; // marked as secret\n```\n\n### Template\n\nCreate reusable email templates:\n\n```typescript\nconst template = new resend.Template(\"welcome\", {\n    name: \"welcome-email\",\n    subject: \"Welcome to our service!\",\n    html: \"\u003ch1\u003eWelcome {{name}}!\u003c/h1\u003e\u003cp\u003eThanks for signing up.\u003c/p\u003e\",\n});\n\nexport const templateId = template.id;\n```\n\n### Webhook\n\nSet up webhooks for email events:\n\n```typescript\nconst webhook = new resend.Webhook(\"events\", {\n    endpoint: \"https://api.example.com/webhooks/resend\",\n    events: [\"email.sent\", \"email.delivered\", \"email.bounced\"],\n});\n\nexport const webhookId = webhook.id;\n```\n\n### Send Email (Function)\n\nSend emails directly via Pulumi:\n\n```typescript\nconst result = resend.sendEmail({\n    from: \"hello@mail.example.com\",\n    to: [\"user@example.com\"],\n    subject: \"Hello from Pulumi!\",\n    html: \"\u003cp\u003eThis email was sent via infrastructure as code.\u003c/p\u003e\",\n});\n\nexport const emailId = result.then(r =\u003e r.emailId);\n```\n\n\u003e **Note**: `sendEmail` is a function (invoke), not a resource. It executes on every `pulumi up` and doesn't maintain state.\n\n### Topic\n\nManage subscription topics that control contact email preferences:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst newsletter = new resend.Topic(\"newsletter\", {\n    name: \"Newsletter\",\n    defaultSubscription: \"opt_in\",\n    description: \"Weekly product updates\",\n    visibility: \"public\",\n});\n\nexport const topicId = newsletter.id;\n```\n\n**Notes:**\n- `defaultSubscription` is immutable after creation; changes require replacement\n- `name`, `description`, and `visibility` can be updated in place\n\n### Event\n\nDefine custom event types that trigger automations:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst userCreated = new resend.Event(\"userCreated\", {\n    name: \"user.created\",\n    schema: {\n        user_id: \"string\",\n        plan: \"string\",\n        trial_days: \"number\",\n    },\n});\n\nexport const eventId = userCreated.id;\n```\n\n**Notes:**\n- Event `name` is immutable; changes require replacement\n- `schema` can be updated in place\n- Names must not start with `resend:` (reserved prefix)\n\n### ContactProperty\n\nDefine custom fields on contacts:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst companyName = new resend.ContactProperty(\"companyName\", {\n    key: \"company_name\",\n    type: \"string\",\n    fallbackValue: \"Unknown\",\n});\n\nexport const propertyId = companyName.id;\n```\n\n**Notes:**\n- `key` and `type` are immutable; changes require replacement\n- Only `fallbackValue` can be updated in place\n- Key must be alphanumeric with underscores, max 50 characters\n\n### Segment\n\nCreate contact segments for targeted broadcasts:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst activeUsers = new resend.Segment(\"activeUsers\", {\n    name: \"Active Users\",\n});\n\nexport const segmentId = activeUsers.id;\n```\n\n**Notes:**\n- Segments are immutable after creation (no update API)\n- Any change to inputs requires delete and recreate\n\n### Automation\n\nCreate multi-step email automation workflows:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst template = new resend.Template(\"welcome\", {\n    name: \"Welcome Email\",\n    html: \"\u003ch1\u003eWelcome!\u003c/h1\u003e\u003cp\u003eThanks for signing up.\u003c/p\u003e\",\n});\n\nconst automation = new resend.Automation(\"welcomeSequence\", {\n    name: \"Welcome Sequence\",\n    status: \"disabled\",\n    steps: [\n        {\n            key: \"trigger\",\n            type: \"trigger\",\n            config: { event_name: \"user.created\" },\n        },\n        {\n            key: \"send_welcome\",\n            type: \"send_email\",\n            config: {\n                template: { id: template.id },\n                subject: \"Welcome aboard!\",\n            },\n        },\n        {\n            key: \"wait_3_days\",\n            type: \"delay\",\n            config: { duration: \"3 days\" },\n        },\n    ],\n    connections: [\n        { from: \"trigger\", to: \"send_welcome\" },\n        { from: \"send_welcome\", to: \"wait_3_days\" },\n    ],\n});\n\nexport const automationId = automation.id;\n```\n\n**Step types:** `trigger`, `send_email`, `delay`, `wait_for_event`, `condition`, `contact_update`, `contact_delete`, `add_to_segment`\n\n**Connection types:** `default`, `condition_met`, `condition_not_met`, `timeout`, `event_received`\n\n### Send Batch Email (Function)\n\nSend up to 100 emails in a single API call:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst result = await resend.sendBatchEmail({\n    emails: [\n        {\n            from: \"hello@mail.example.com\",\n            to: [\"user1@example.com\"],\n            subject: \"Hello User 1\",\n            html: \"\u003cp\u003eHello!\u003c/p\u003e\",\n        },\n        {\n            from: \"hello@mail.example.com\",\n            to: [\"user2@example.com\"],\n            subject: \"Hello User 2\",\n            html: \"\u003cp\u003eHello!\u003c/p\u003e\",\n        },\n    ],\n});\n```\n\n### Send Event (Function)\n\nTrigger custom events for automations:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst result = await resend.sendEvent({\n    event: \"user.created\",\n    email: \"newuser@example.com\",\n    payload: {\n        plan: \"pro\",\n        trial_days: 14,\n    },\n});\n```\n\n**Notes:**\n- Exactly one of `contactId` or `email` must be provided\n\n### Send Broadcast (Function)\n\nCreate and send a one-time email campaign to a segment:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst customers = new resend.Segment(\"customers\", {\n    name: \"All Customers\",\n});\n\nconst result = await resend.sendBroadcast({\n    from: \"updates@mail.example.com\",\n    subject: \"Important Announcement\",\n    segmentId: customers.id,\n    html: \"\u003cp\u003eHello!\u003c/p\u003e\",\n    previewText: \"We have exciting news...\",\n});\n```\n\n**Notes:**\n- Creates and sends the broadcast atomically\n- Supports scheduled sending via `scheduledAt` (ISO 8601 timestamp)\n\n## Examples\n\n### Complete Email Platform Setup\n\nSet up a full email platform with domain verification, templates, topics, and automation:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\n// 1. Domain with tracking enabled\nconst domain = new resend.Domain(\"mail\", {\n    name: \"mail.example.com\",\n    region: \"us-east-1\",\n    openTracking: true,\n    clickTracking: true,\n});\n\n// 2. Verify the domain (polls until DNS records are confirmed)\nconst verification = new resend.DomainVerification(\"verify\", {\n    domainId: domain.id,\n});\n\n// 3. Scoped API key for sending only\nconst sendingKey = new resend.ApiKey(\"sender\", {\n    name: \"production-sender\",\n    permission: \"sending_access\",\n    domainId: domain.id,\n});\n\n// 4. Subscription topics\nconst newsletter = new resend.Topic(\"newsletter\", {\n    name: \"Newsletter\",\n    defaultSubscription: \"opt_in\",\n    description: \"Weekly product updates and tips\",\n    visibility: \"public\",\n});\n\nconst marketing = new resend.Topic(\"marketing\", {\n    name: \"Marketing\",\n    defaultSubscription: \"opt_out\",\n    description: \"Promotional offers and announcements\",\n    visibility: \"public\",\n});\n\n// 5. Contact properties for personalization\nconst companyName = new resend.ContactProperty(\"company\", {\n    key: \"company_name\",\n    type: \"string\",\n    fallbackValue: \"there\",\n});\n\nconst plan = new resend.ContactProperty(\"plan\", {\n    key: \"plan\",\n    type: \"string\",\n    fallbackValue: \"free\",\n});\n\n// 6. Webhook for delivery tracking\nconst webhook = new resend.Webhook(\"delivery-events\", {\n    endpoint: \"https://api.example.com/webhooks/resend\",\n    events: [\n        \"email.sent\",\n        \"email.delivered\",\n        \"email.bounced\",\n        \"email.complained\",\n        \"email.opened\",\n        \"email.clicked\",\n    ],\n});\n\nexport const domainId = domain.id;\nexport const dnsRecords = domain.records;\nexport const apiKeyToken = sendingKey.token;\n```\n\n### Welcome Email Automation\n\nBuild a multi-step onboarding sequence triggered when users sign up:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\n// Define the trigger event\nconst signupEvent = new resend.Event(\"signup\", {\n    name: \"user.signup\",\n    schema: {\n        first_name: \"string\",\n        plan: \"string\",\n        trial_days: \"number\",\n    },\n});\n\n// Create email templates\nconst welcomeTemplate = new resend.Template(\"welcome\", {\n    name: \"Welcome Email\",\n    subject: \"Welcome to Example, {{first_name}}!\",\n    from: \"hello@mail.example.com\",\n    html: `\n        \u003ch1\u003eWelcome, {{first_name}}!\u003c/h1\u003e\n        \u003cp\u003eThanks for joining us on the {{plan}} plan.\u003c/p\u003e\n        \u003cp\u003eYou have {{trial_days}} days to explore everything.\u003c/p\u003e\n    `,\n});\n\nconst tipsTemplate = new resend.Template(\"tips\", {\n    name: \"Getting Started Tips\",\n    subject: \"3 tips to get the most out of Example\",\n    from: \"hello@mail.example.com\",\n    html: \"\u003ch1\u003ePro tips for you\u003c/h1\u003e\u003cp\u003eHere's how to get started...\u003c/p\u003e\",\n});\n\nconst checkInTemplate = new resend.Template(\"checkin\", {\n    name: \"Check-in Email\",\n    subject: \"How's it going, {{first_name}}?\",\n    from: \"hello@mail.example.com\",\n    html: \"\u003ch1\u003eHey {{first_name}}\u003c/h1\u003e\u003cp\u003eJust checking in...\u003c/p\u003e\",\n});\n\n// Build the automation workflow\nconst onboarding = new resend.Automation(\"onboarding\", {\n    name: \"New User Onboarding\",\n    status: \"enabled\",\n    steps: [\n        {\n            key: \"trigger\",\n            type: \"trigger\",\n            config: { event_name: \"user.signup\" },\n        },\n        {\n            key: \"welcome\",\n            type: \"send_email\",\n            config: {\n                template: { id: welcomeTemplate.id },\n            },\n        },\n        {\n            key: \"wait_2_days\",\n            type: \"delay\",\n            config: { duration: \"2 days\" },\n        },\n        {\n            key: \"tips\",\n            type: \"send_email\",\n            config: {\n                template: { id: tipsTemplate.id },\n            },\n        },\n        {\n            key: \"wait_5_days\",\n            type: \"delay\",\n            config: { duration: \"5 days\" },\n        },\n        {\n            key: \"checkin\",\n            type: \"send_email\",\n            config: {\n                template: { id: checkInTemplate.id },\n            },\n        },\n    ],\n    connections: [\n        { from: \"trigger\", to: \"welcome\" },\n        { from: \"welcome\", to: \"wait_2_days\" },\n        { from: \"wait_2_days\", to: \"tips\" },\n        { from: \"tips\", to: \"wait_5_days\" },\n        { from: \"wait_5_days\", to: \"checkin\" },\n    ],\n});\n\n// Trigger the automation for a new user (invoke)\nconst triggerSignup = resend.sendEvent({\n    event: \"user.signup\",\n    email: \"newuser@example.com\",\n    payload: {\n        first_name: \"Alice\",\n        plan: \"pro\",\n        trial_days: 14,\n    },\n});\n```\n\n### Domain Setup with AWS Route53\n\nUse domain DNS records to configure Route53 automatically:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\nimport * as aws from \"@pulumi/aws\";\n\nconst domain = new resend.Domain(\"mail\", {\n    name: \"mail.example.com\",\n    region: \"us-east-1\",\n});\n\nconst zone = aws.route53.getZone({ name: \"example.com\" });\n\n// Create DNS records from the domain's output\ndomain.records.apply(records =\u003e {\n    records.forEach((rec, i) =\u003e {\n        new aws.route53.Record(`dns-${i}`, {\n            zoneId: zone.then(z =\u003e z.zoneId),\n            name: rec.name,\n            type: rec.type,\n            records: [rec.value],\n            ttl: parseInt(rec.ttl) || 300,\n        });\n    });\n});\n\n// Verify after DNS records are created\nconst verification = new resend.DomainVerification(\"verify\", {\n    domainId: domain.id,\n});\n```\n\n### Conditional Automation with Branching\n\nCreate an automation with conditional logic based on user properties:\n\n```typescript\nimport * as resend from \"@humanlayer/pulumi-resend\";\n\nconst automation = new resend.Automation(\"trial-followup\", {\n    name: \"Trial Expiry Follow-up\",\n    status: \"enabled\",\n    steps: [\n        {\n            key: \"trigger\",\n            type: \"trigger\",\n            config: { event_name: \"trial.expiring\" },\n        },\n        {\n            key: \"check_plan\",\n            type: \"condition\",\n            config: {\n                type: \"rule\",\n                field: \"plan\",\n                operator: \"equals\",\n                value: \"enterprise\",\n            },\n        },\n        {\n            key: \"enterprise_email\",\n            type: \"send_email\",\n            config: {\n                template: { id: \"tmpl_enterprise_upsell\" },\n                subject: \"Your enterprise trial is ending soon\",\n            },\n        },\n        {\n            key: \"standard_email\",\n            type: \"send_email\",\n            config: {\n                template: { id: \"tmpl_standard_upsell\" },\n                subject: \"Upgrade before your trial ends\",\n            },\n        },\n    ],\n    connections: [\n        { from: \"trigger\", to: \"check_plan\" },\n        { from: \"check_plan\", to: \"enterprise_email\", type: \"condition_met\" },\n        { from: \"check_plan\", to: \"standard_email\", type: \"condition_not_met\" },\n    ],\n});\n```\n\n### Importing Existing Resources\n\nImport existing Resend resources into Pulumi state:\n\n```bash\n# Import an existing domain\npulumi import resend:index:Domain myDomain d_abc123\n\n# Import an existing API key\npulumi import resend:index:ApiKey myKey ak_xyz789\n\n# Import an existing webhook\npulumi import resend:index:Webhook myWebhook wh_def456\n\n# Import an existing template\npulumi import resend:index:Template myTemplate tmpl_ghi789\n```\n\n### YAML Example\n\n```yaml\nname: resend-email-infra\nruntime: yaml\n\nresources:\n  domain:\n    type: resend:index:Domain\n    properties:\n      name: mail.example.com\n      region: us-east-1\n      openTracking: true\n\n  apiKey:\n    type: resend:index:ApiKey\n    properties:\n      name: my-sending-key\n      permission: sending_access\n\n  newsletter:\n    type: resend:index:Topic\n    properties:\n      name: Newsletter\n      defaultSubscription: opt_in\n      visibility: public\n\n  welcomeTemplate:\n    type: resend:index:Template\n    properties:\n      name: Welcome\n      subject: Welcome!\n      html: \"\u003ch1\u003eWelcome!\u003c/h1\u003e\"\n\n  webhook:\n    type: resend:index:Webhook\n    properties:\n      endpoint: https://api.example.com/webhooks/resend\n      events:\n        - email.delivered\n        - email.bounced\n\noutputs:\n  domainId: ${domain.id}\n  dnsRecords: ${domain.records}\n  apiKeyToken: ${apiKey.token}\n```\n\n## Resources\n\n| Resource | Description | Update | Notes |\n|----------|-------------|--------|-------|\n| `Domain` | Email sending domain with DNS records | In-place | `name`/`region` immutable |\n| `DomainVerification` | Triggers DNS verification for a domain | No-op | Idempotent, delete is no-op |\n| `ApiKey` | API key for authentication | Replace | All fields immutable, token is secret |\n| `Template` | Reusable email template | In-place | Full CRUD |\n| `Webhook` | Webhook endpoint for email events | In-place | Full CRUD |\n| `Topic` | Subscription topic for contact preferences | In-place | `defaultSubscription` immutable |\n| `Event` | Custom event type for automation triggers | In-place | `name` immutable, `schema` updatable |\n| `ContactProperty` | Custom field definition on contacts | In-place | `key`/`type` immutable |\n| `Segment` | Contact segment for targeted broadcasts | Replace | No update API |\n| `Automation` | Multi-step email automation workflow | In-place | Steps/connections replaced together |\n\n## Functions\n\n| Function | Description | Notes |\n|----------|-------------|-------|\n| `sendEmail` | Send a single email | Runs on every `pulumi up` |\n| `sendBatchEmail` | Send up to 100 emails in one call | Max 50 recipients per email |\n| `sendEvent` | Trigger a custom event for automations | Requires `contactId` or `email` |\n| `sendBroadcast` | Create and send a broadcast to a segment | Atomic create+send |\n\n## Development\n\n```bash\n# Build the provider\nmake provider\n\n# Generate schema\nmake schema\n\n# Generate TypeScript SDK\nmake codegen\n\n# Run tests\ngo test ./...\n\n# Build and test everything\nmake provider \u0026\u0026 make schema \u0026\u0026 make codegen \u0026\u0026 cd sdk/nodejs \u0026\u0026 npm install \u0026\u0026 npm run build\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanlayer%2Fpulumi-resend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhumanlayer%2Fpulumi-resend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanlayer%2Fpulumi-resend/lists"}