Compare commits

...

39 Commits

Author SHA1 Message Date
Waleed Latif
10bfbb61d0 feat(doordash): add DoorDash Drive integration with 13 API operations 2026-03-29 18:50:30 -07:00
Waleed
14089f7dbb v0.6.14: performance improvements, connectors UX, collapsed sidebar actions 2026-03-27 13:07:59 -07:00
Waleed
e615816dce v0.6.13: emcn standardization, granola and ketch integrations, security hardening, connectors improvements 2026-03-27 00:16:37 -07:00
Waleed
ca87d7ce29 v0.6.12: billing, blogs UI 2026-03-26 01:19:23 -07:00
Waleed
6bebbc5e29 v0.6.11: billing fixes, rippling, hubspot, UI improvements, demo modal 2026-03-25 22:54:56 -07:00
Waleed
7b572f1f61 v0.6.10: tour fix, connectors reliability improvements, tooltip gif fixes 2026-03-24 21:38:19 -07:00
Vikhyath Mondreti
ed9a71f0af v0.6.9: general ux improvements for tables, mothership 2026-03-24 17:03:24 -07:00
Siddharth Ganesan
c78c870fda v0.6.8: mothership tool loop
v0.6.8: mothership tool loop
2026-03-24 04:06:19 -07:00
Waleed
19442f19e2 v0.6.7: kb improvements, edge z index fix, captcha, new trust center, block classifications 2026-03-21 12:43:33 -07:00
Waleed
1731a4d7f0 v0.6.6: landing improvements, styling consistency, mothership table renaming 2026-03-19 23:58:30 -07:00
Waleed
9fcd02fd3b v0.6.5: email validation, integrations page, mothership and custom tool fixes 2026-03-19 16:08:30 -07:00
Waleed
ff7b5b528c v0.6.4: subflows, docusign, ashby new tools, box, workday, billing bug fixes 2026-03-18 23:12:36 -07:00
Waleed
30f2d1a0fc v0.6.3: hubspot integration, kb block improvements 2026-03-18 11:19:55 -07:00
Waleed
4bd0731871 v0.6.2: mothership stability, chat iframe embedding, KB upserts, new blog post 2026-03-18 03:29:39 -07:00
Waleed
4f3bc37fe4 v0.6.1: added better auth admin plugin 2026-03-17 15:16:16 -07:00
Waleed
84d6fdc423 v0.6: mothership, tables, connectors 2026-03-17 12:21:15 -07:00
Vikhyath Mondreti
4c12914d35 v0.5.113: jira, ashby, google ads, grain updates 2026-03-12 22:54:25 -07:00
Waleed
e9bdc57616 v0.5.112: trace spans improvements, fathom integration, jira fixes, canvas navigation updates 2026-03-12 13:30:20 -07:00
Vikhyath Mondreti
36612ae42a v0.5.111: non-polling webhook execs off trigger.dev, gmail subject headers, webhook trigger configs (#3530) 2026-03-11 17:47:28 -07:00
Waleed
1c2c2c65d4 v0.5.110: webhook execution speedups, SSRF patches 2026-03-11 15:00:24 -07:00
Waleed
ecd3536a72 v0.5.109: obsidian and evernote integrations, slack fixes, remove memory instrumentation 2026-03-09 10:40:37 -07:00
Vikhyath Mondreti
8c0a2e04b1 v0.5.108: workflow input params in agent tools, bun upgrade, dropdown selectors for 14 blocks 2026-03-06 21:02:25 -08:00
Waleed
6586c5ce40 v0.5.107: new reddit, slack tools 2026-03-05 22:48:20 -08:00
Vikhyath Mondreti
3ce947566d v0.5.106: condition block and legacy kbs fixes, GPT 5.4 2026-03-05 17:30:05 -08:00
Waleed
70c36cb7aa v0.5.105: slack remove reaction, nested subflow locks fix, servicenow pagination, memory improvements 2026-03-04 22:38:26 -08:00
Waleed
f1ec5fe824 v0.5.104: memory improvements, nested subflows, careers page redirect, brandfetch, google meet 2026-03-03 23:45:29 -08:00
Waleed
e07e3c34cc v0.5.103: memory util instrumentation, API docs, amplitude, google pagespeed insights, pagerduty 2026-03-01 23:27:02 -08:00
Waleed
0d2e6ff31d v0.5.102: new integrations, new tools, ci speedups, memory leak instrumentation 2026-02-28 12:48:10 -08:00
Waleed
4fd0989264 v0.5.101: circular dependency mitigation, confluence enhancements, google tasks and bigquery integrations, workflow lock 2026-02-26 15:04:53 -08:00
Waleed
67f8a687f6 v0.5.100: multiple credentials, 40% speedup, gong, attio, audit log improvements 2026-02-25 00:28:25 -08:00
Waleed
af592349d3 v0.5.99: local dev improvements, live workflow logs in terminal 2026-02-23 00:24:49 -08:00
Waleed
0d86ea01f0 v0.5.98: change detection improvements, rate limit and code execution fixes, removed retired models, hex integration 2026-02-21 18:07:40 -08:00
Waleed
115f04e989 v0.5.97: oidc discovery for copilot mcp 2026-02-21 02:06:25 -08:00
Waleed
34d92fae89 v0.5.96: sim oauth provider, slack ephemeral message tool and blockkit support 2026-02-20 18:22:20 -08:00
Waleed
67aa4bb332 v0.5.95: gemini 3.1 pro, cloudflare, dataverse, revenuecat, redis, upstash, algolia tools; isolated-vm robustness improvements, tables backend (#3271)
* feat(tools): advanced fields for youtube, vercel; added cloudflare and dataverse tools (#3257)

* refactor(vercel): mark optional fields as advanced mode

Move optional/power-user fields behind the advanced toggle:
- List Deployments: project filter, target, state
- Create Deployment: project ID override, redeploy from, target
- List Projects: search
- Create/Update Project: framework, build/output/install commands
- Env Vars: variable type
- Webhooks: project IDs filter
- Checks: path, details URL
- Team Members: role filter
- All operations: team ID scope

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(youtube): mark optional params as advanced mode

Hide pagination, sort order, and filter fields behind the advanced
toggle for a cleaner default UX across all YouTube operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* added advanced fields for vercel and youtube, added cloudflare and dataverse block

* addded desc for dataverse

* add more tools

* ack comment

* more

* ops

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat(tables): added tables (#2867)

* updates

* required

* trashy table viewer

* updates

* updates

* filtering ui

* updates

* updates

* updates

* one input mode

* format

* fix lints

* improved errors

* updates

* updates

* chages

* doc strings

* breaking down file

* update comments with ai

* updates

* comments

* changes

* revert

* updates

* dedupe

* updates

* updates

* updates

* refactoring

* renames & refactors

* refactoring

* updates

* undo

* update db

* wand

* updates

* fix comments

* fixes

* simplify comments

* u[dates

* renames

* better comments

* validation

* updates

* updates

* updates

* fix sorting

* fix appearnce

* updating prompt to make it user sort

* rm

* updates

* rename

* comments

* clean comments

* simplicifcaiton

* updates

* updates

* refactor

* reduced type confusion

* undo

* rename

* undo changes

* undo

* simplify

* updates

* updates

* revert

* updates

* db updates

* type fix

* fix

* fix error handling

* updates

* docs

* docs

* updates

* rename

* dedupe

* revert

* uncook

* updates

* fix

* fix

* fix

* fix

* prepare merge

* readd migrations

* add back missed code

* migrate enrichment logic to general abstraction

* address bugbot concerns

* adhere to size limits for tables

* remove conflicting migration

* add back migrations

* fix tables auth

* fix permissive auth

* fix lint

* reran migrations

* migrate to use tanstack query for all server state

* update table-selector

* update names

* added tables to permission groups, updated subblock types

---------

Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
Co-authored-by: waleed <walif6@gmail.com>

* fix(snapshot): changed insert to upsert when concurrent identical child workflows are running (#3259)

* fix(snapshot): changed insert to upsert when concurrent identical child workflows are running

* fixed ci tests failing

* fix(workflows): disallow duplicate workflow names at the same folder level (#3260)

* feat(tools): added redis, upstash, algolia, and revenuecat (#3261)

* feat(tools): added redis, upstash, algolia, and revenuecat

* ack comment

* feat(models): add gemini-3.1-pro-preview and update gemini-3-pro thinking levels (#3263)

* fix(audit-log): lazily resolve actor name/email when missing (#3262)

* fix(blocks): move type coercions from tools.config.tool to tools.config.params (#3264)

* fix(blocks): move type coercions from tools.config.tool to tools.config.params

Number() coercions in tools.config.tool ran at serialization time before
variable resolution, destroying dynamic references like <block.result.count>
by converting them to NaN/null. Moved all coercions to tools.config.params
which runs at execution time after variables are resolved.

Fixed in 15 blocks: exa, arxiv, sentry, incidentio, wikipedia, ahrefs,
posthog, elasticsearch, dropbox, hunter, lemlist, spotify, youtube, grafana,
parallel. Also added mode: 'advanced' to optional exa fields.

Closes #3258

* fix(blocks): address PR review — move remaining param mutations from tool() to params()

- Moved field mappings from tool() to params() in grafana, posthog,
  lemlist, spotify, dropbox (same dynamic reference bug)
- Fixed parallel.ts excerpts/full_content boolean logic
- Fixed parallel.ts search_queries empty case (must set undefined)
- Fixed elasticsearch.ts timeout not included when already ends with 's'
- Restored dropbox.ts tool() switch for proper default fallback

* fix(blocks): restore field renames to tool() for serialization-time validation

Field renames (e.g. personalApiKey→apiKey) must be in tool() because
validateRequiredFieldsBeforeExecution calls selectToolId()→tool() then
checks renamed field names on params. Only type coercions (Number(),
boolean) stay in params() to avoid destroying dynamic variable references.

* improvement(resolver): resovled empty sentinel to not pass through unexecuted valid refs to text inputs (#3266)

* fix(blocks): add required constraint for serviceDeskId in JSM block (#3268)

* fix(blocks): add required constraint for serviceDeskId in JSM block

* fix(blocks): rename custom field values to request field values in JSM create request

* fix(trigger): add isolated-vm support to trigger.dev container builds (#3269)

Scheduled workflow executions running in trigger.dev containers were
failing to spawn isolated-vm workers because the native module wasn't
available in the container. This caused loop condition evaluation to
silently fail and exit after one iteration.

- Add isolated-vm to build.external and additionalPackages in trigger config
- Include isolated-vm-worker.cjs via additionalFiles for child process spawning
- Add fallback path resolution for worker file in trigger.dev environment

* fix(tables): hide tables from sidebar and block registry (#3270)

* fix(tables): hide tables from sidebar and block registry

* fix(trigger): add isolated-vm support to trigger.dev container builds (#3269)

Scheduled workflow executions running in trigger.dev containers were
failing to spawn isolated-vm workers because the native module wasn't
available in the container. This caused loop condition evaluation to
silently fail and exit after one iteration.

- Add isolated-vm to build.external and additionalPackages in trigger config
- Include isolated-vm-worker.cjs via additionalFiles for child process spawning
- Add fallback path resolution for worker file in trigger.dev environment

* lint

* fix(trigger): update node version to align with main app (#3272)

* fix(build): fix corrupted sticky disk cache on blacksmith (#3273)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Lakee Sivaraya <71339072+lakeesiv@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
2026-02-20 13:43:07 -08:00
Waleed
15ace5e63f v0.5.94: vercel integration, folder insertion, migrated tracking redirects to rewrites 2026-02-18 16:53:34 -08:00
Waleed
fdca73679d v0.5.93: NextJS config changes, MCP and Blocks whitelisting, copilot keyboard shortcuts, audit logs 2026-02-18 12:10:05 -08:00
Waleed
da46a387c9 v0.5.92: shortlinks, copilot scrolling stickiness, pagination 2026-02-17 15:13:21 -08:00
Waleed
b7e377ec4b v0.5.91: docs i18n, turborepo upgrade 2026-02-16 00:36:05 -08:00
26 changed files with 3948 additions and 188 deletions

View File

@@ -1193,6 +1193,18 @@ export function DocuSignIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function DoordashIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 132 75' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='132' height='75' rx='8' fill='white' />
<path
d='M126.9 17.8C121 6.8 109.6 0 97.2 0H3.2C1.4 0 0 1.5 0 3.3c0 .8.3 1.7.9 2.3l20.5 20.6c1.8 1.8 4.3 2.8 6.8 2.8h66.3c4.7 0 8.6 3.7 8.6 8.5 0 4.7-3.7 8.6-8.5 8.6H49c-1.8 0-3.2 1.5-3.2 3.3 0 .9.3 1.7.9 2.3l20.5 20.6C69 74 71.5 75 74 75h20.7c26.9 0 47.2-28.7 32.2-57.2'
fill='#FF3008'
/>
</svg>
)
}
export function DiscordIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg

View File

@@ -33,8 +33,9 @@ import {
DatadogIcon,
DevinIcon,
DiscordIcon,
DocumentIcon,
DocuSignIcon,
DocumentIcon,
DoordashIcon,
DropboxIcon,
DsPyIcon,
DubIcon,
@@ -50,8 +51,8 @@ import {
FirecrawlIcon,
FirefliesIcon,
GammaIcon,
GithubIcon,
GitLabIcon,
GithubIcon,
GmailIcon,
GongIcon,
GoogleAdsIcon,
@@ -97,9 +98,9 @@ import {
LinkupIcon,
LoopsIcon,
LumaIcon,
MailServerIcon,
MailchimpIcon,
MailgunIcon,
MailServerIcon,
Mem0Icon,
MicrosoftDataverseIcon,
MicrosoftExcelIcon,
@@ -137,6 +138,8 @@ import {
RevenueCatIcon,
RipplingIcon,
S3Icon,
SQSIcon,
STTIcon,
SalesforceIcon,
SearchIcon,
SendgridIcon,
@@ -148,19 +151,17 @@ import {
SimilarwebIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
SshIcon,
STTIcon,
StagehandIcon,
StripeIcon,
SupabaseIcon,
TTSIcon,
TavilyIcon,
TelegramIcon,
TextractIcon,
TinybirdIcon,
TranslateIcon,
TrelloIcon,
TTSIcon,
TwilioIcon,
TypeformIcon,
UpstashIcon,
@@ -172,11 +173,11 @@ import {
WikipediaIcon,
WordpressIcon,
WorkdayIcon,
xIcon,
YouTubeIcon,
ZendeskIcon,
ZepIcon,
ZoomIcon,
xIcon,
} from '@/components/icons'
type IconComponent = ComponentType<SVGProps<SVGSVGElement>>
@@ -210,6 +211,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
devin: DevinIcon,
discord: DiscordIcon,
docusign: DocuSignIcon,
doordash: DoordashIcon,
dropbox: DropboxIcon,
dspy: DsPyIcon,
dub: DubIcon,

View File

@@ -0,0 +1,460 @@
---
title: DoorDash
description: Create and manage DoorDash Drive deliveries, businesses, and stores
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
<BlockInfoCard
type="doordash"
color="#FF3008"
/>
## Overview
The DoorDash block integrates with the [DoorDash Drive API](https://developer.doordash.com/en-US/docs/drive/overview/) to enable last-mile delivery orchestration directly from your workflows.
### Authentication
DoorDash Drive uses **JWT-based authentication** with three credentials:
- **Developer ID** — Your DoorDash developer account identifier
- **Key ID** — The key identifier for signing requests
- **Signing Secret** — The secret used to sign JWT tokens (Base64-encoded)
You can find these credentials in the [DoorDash Developer Portal](https://developer.doordash.com/portal/integration/drive/credentials).
### Recommended Workflow
The typical delivery flow is:
1. **Create Quote** — Validate delivery coverage, get pricing and ETAs
2. **Accept Quote** — Confirm the quote to create the delivery (must be within 5 minutes)
3. **Get Delivery** — Track delivery status and Dasher assignment
4. **Update Delivery** — Modify tip or dropoff details if needed
5. **Cancel Delivery** — Cancel before a Dasher is assigned
Alternatively, use **Create Delivery** to skip the quote step and create a delivery directly.
### Business & Store Management
DoorDash Drive also supports managing business entities and store locations:
- **Create/List/Update Business** — Organize your delivery operations under business entities
- **Create/List/Get/Update Store** — Manage store locations under businesses for pickup
### Important Notes
- DoorDash Drive is a **delivery-only** API — it does not support placing food/product orders
- Order values and fees are in **cents** (e.g., `1999` = $19.99)
- `pickupTime` and `dropoffTime` are **mutually exclusive** — set one or the other, not both
- Delivery cancellation is only possible **before** a Dasher is assigned
## Tools
### `doordash_create_quote`
Creates a delivery quote to validate coverage, pricing, and estimated delivery times.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | Unique delivery identifier |
| `pickupAddress` | string | Yes | Pickup address \(e.g., "901 Market Street 6th Floor San Francisco, CA 94103"\) |
| `pickupPhoneNumber` | string | Yes | Pickup phone number \(e.g., "+16505555555"\) |
| `pickupBusinessName` | string | Yes | Pickup business name |
| `dropoffAddress` | string | Yes | Dropoff address |
| `dropoffPhoneNumber` | string | Yes | Dropoff phone number |
| `dropoffBusinessName` | string | Yes | Dropoff contact or business name |
| `orderValue` | string | Yes | Order value in cents \(e.g., "1999" for $19.99\) |
| `pickupInstructions` | string | No | Instructions for pickup |
| `dropoffInstructions` | string | No | Instructions for dropoff |
| `tip` | string | No | Tip amount in cents |
| `dropoffContactSendNotifications` | string | No | Send SMS notifications to recipient \(true/false\) |
| `actionIfUndeliverable` | string | No | Action if undeliverable \(e.g., "return_to_pickup"\) |
| `contactlessDropoff` | string | No | Contactless doorstep delivery with photo verification \(true/false\) |
| `dropoffRequiresSignature` | string | No | Require signature at dropoff \(true/false\) |
| `dropoffContactGivenName` | string | No | Recipient first name |
| `dropoffContactFamilyName` | string | No | Recipient last name |
| `pickupTime` | string | No | Scheduled pickup time \(ISO 8601, mutually exclusive with dropoffTime\) |
| `dropoffTime` | string | No | Scheduled dropoff time \(ISO 8601, mutually exclusive with pickupTime\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status |
| `fee` | number | Delivery fee in cents |
| `currency` | string | Fee currency code |
| `pickupTimeEstimated` | string | Estimated pickup time |
| `dropoffTimeEstimated` | string | Estimated dropoff time |
### `doordash_accept_quote`
Accepts a delivery quote to formally create the delivery. Must be called within 5 minutes of creating the quote.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | External delivery ID from the quote |
| `tip` | string | No | Tip amount in cents |
| `dropoffPhoneNumber` | string | No | Updated dropoff phone number |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status |
| `fee` | number | Delivery fee in cents |
| `tip` | number | Tip amount in cents |
| `orderValue` | number | Order value in cents |
| `currency` | string | Fee currency code |
| `trackingUrl` | string | Delivery tracking URL |
| `supportReference` | string | Support reference ID |
| `dasherName` | string | Assigned Dasher name |
| `dasherId` | number | Assigned Dasher ID |
| `contactlessDropoff` | boolean | Whether contactless dropoff was used |
| `dropoffVerificationImageUrl` | string | Photo verification URL at dropoff |
| `cancellationReason` | string | Reason for cancellation |
| `pickupTimeEstimated` | string | Estimated pickup time |
| `pickupTimeActual` | string | Actual pickup time |
| `dropoffTimeEstimated` | string | Estimated dropoff time |
| `dropoffTimeActual` | string | Actual dropoff time |
| `pickupAddress` | string | Pickup address |
| `dropoffAddress` | string | Dropoff address |
| `updatedAt` | string | Last updated timestamp |
### `doordash_create_delivery`
Creates a delivery directly without a prior quote. Skips price confirmation.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | Unique delivery identifier |
| `pickupAddress` | string | Yes | Pickup address \(e.g., "901 Market Street 6th Floor San Francisco, CA 94103"\) |
| `pickupPhoneNumber` | string | Yes | Pickup phone number \(e.g., "+16505555555"\) |
| `pickupBusinessName` | string | Yes | Pickup business name |
| `dropoffAddress` | string | Yes | Dropoff address |
| `dropoffPhoneNumber` | string | Yes | Dropoff phone number |
| `dropoffBusinessName` | string | Yes | Dropoff contact or business name |
| `orderValue` | string | Yes | Order value in cents \(e.g., "1999" for $19.99\) |
| `pickupInstructions` | string | No | Instructions for pickup |
| `dropoffInstructions` | string | No | Instructions for dropoff |
| `tip` | string | No | Tip amount in cents |
| `dropoffContactSendNotifications` | string | No | Send SMS notifications to recipient \(true/false\) |
| `actionIfUndeliverable` | string | No | Action if undeliverable \(e.g., "return_to_pickup"\) |
| `contactlessDropoff` | string | No | Contactless doorstep delivery with photo verification \(true/false\) |
| `dropoffRequiresSignature` | string | No | Require signature at dropoff \(true/false\) |
| `dropoffContactGivenName` | string | No | Recipient first name |
| `dropoffContactFamilyName` | string | No | Recipient last name |
| `pickupTime` | string | No | Scheduled pickup time \(ISO 8601, mutually exclusive with dropoffTime\) |
| `dropoffTime` | string | No | Scheduled dropoff time \(ISO 8601, mutually exclusive with pickupTime\) |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status |
| `fee` | number | Delivery fee in cents |
| `tip` | number | Tip amount in cents |
| `orderValue` | number | Order value in cents |
| `currency` | string | Fee currency code |
| `trackingUrl` | string | Delivery tracking URL |
| `supportReference` | string | Support reference ID |
| `dasherName` | string | Assigned Dasher name |
| `dasherId` | number | Assigned Dasher ID |
| `contactlessDropoff` | boolean | Whether contactless dropoff was used |
| `dropoffVerificationImageUrl` | string | Photo verification URL at dropoff |
| `cancellationReason` | string | Reason for cancellation |
| `pickupTimeEstimated` | string | Estimated pickup time |
| `pickupTimeActual` | string | Actual pickup time |
| `dropoffTimeEstimated` | string | Estimated dropoff time |
| `dropoffTimeActual` | string | Actual dropoff time |
| `pickupAddress` | string | Pickup address |
| `dropoffAddress` | string | Dropoff address |
| `updatedAt` | string | Last updated timestamp |
### `doordash_get_delivery`
Retrieves the current status and details of a delivery.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | External delivery ID to look up |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status |
| `fee` | number | Delivery fee in cents |
| `tip` | number | Tip amount in cents |
| `orderValue` | number | Order value in cents |
| `currency` | string | Fee currency code |
| `trackingUrl` | string | Delivery tracking URL |
| `supportReference` | string | Support reference ID |
| `dasherName` | string | Assigned Dasher name |
| `dasherId` | number | Assigned Dasher ID |
| `contactlessDropoff` | boolean | Whether contactless dropoff was used |
| `dropoffVerificationImageUrl` | string | Photo verification URL at dropoff |
| `cancellationReason` | string | Reason for cancellation |
| `pickupTimeEstimated` | string | Estimated pickup time |
| `pickupTimeActual` | string | Actual pickup time |
| `dropoffTimeEstimated` | string | Estimated dropoff time |
| `dropoffTimeActual` | string | Actual dropoff time |
| `pickupAddress` | string | Pickup address |
| `dropoffAddress` | string | Dropoff address |
| `updatedAt` | string | Last updated timestamp |
### `doordash_update_delivery`
Updates a delivery. Only tip and dropoff details can be modified after creation.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | External delivery ID to update |
| `tip` | string | No | Updated tip amount in cents |
| `dropoffPhoneNumber` | string | No | Updated dropoff phone number |
| `dropoffInstructions` | string | No | Updated dropoff instructions |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status |
| `fee` | number | Delivery fee in cents |
| `tip` | number | Tip amount in cents |
| `orderValue` | number | Order value in cents |
| `currency` | string | Fee currency code |
| `trackingUrl` | string | Delivery tracking URL |
| `supportReference` | string | Support reference ID |
| `dasherName` | string | Assigned Dasher name |
| `dasherId` | number | Assigned Dasher ID |
| `contactlessDropoff` | boolean | Whether contactless dropoff was used |
| `dropoffVerificationImageUrl` | string | Photo verification URL at dropoff |
| `cancellationReason` | string | Reason for cancellation |
| `pickupTimeEstimated` | string | Estimated pickup time |
| `pickupTimeActual` | string | Actual pickup time |
| `dropoffTimeEstimated` | string | Estimated dropoff time |
| `dropoffTimeActual` | string | Actual dropoff time |
| `pickupAddress` | string | Pickup address |
| `dropoffAddress` | string | Dropoff address |
| `updatedAt` | string | Last updated timestamp |
### `doordash_cancel_delivery`
Cancels a delivery. Cannot be used after a Dasher has been assigned to the delivery.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | DoorDash Key ID |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalDeliveryId` | string | Yes | External delivery ID to cancel |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalDeliveryId` | string | External delivery ID |
| `deliveryStatus` | string | Delivery status \(cancelled\) |
### `doordash_create_business`
Creates a new business entity for organizing delivery locations.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Unique business identifier |
| `name` | string | Yes | No description |
| `description` | string | No | Business description |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalBusinessId` | string | Business ID |
| `name` | string | Business name |
| `description` | string | Business description |
| `activationStatus` | string | Activation status |
### `doordash_list_businesses`
Lists all businesses owned by the developer.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `businesses` | array | List of businesses |
| ↳ `externalBusinessId` | string | Business ID |
| ↳ `name` | string | Business name |
| ↳ `description` | string | Business description |
| ↳ `activationStatus` | string | Activation status |
### `doordash_update_business`
Updates a business entity name or description.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Business ID to update |
| `name` | string | No | Updated business name |
| `description` | string | No | Updated business description |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalBusinessId` | string | Business ID |
| `name` | string | Business name |
| `description` | string | Business description |
| `activationStatus` | string | Activation status |
### `doordash_create_store`
Creates a store location under a business for delivery pickup.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Parent business ID |
| `externalStoreId` | string | Yes | Unique store identifier |
| `name` | string | Yes | No description |
| `phoneNumber` | string | Yes | Store phone number |
| `address` | string | Yes | No description |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalStoreId` | string | Store ID |
| `name` | string | Store name |
| `phoneNumber` | string | Store phone number |
| `address` | string | Store address |
### `doordash_list_stores`
Lists all stores under a business.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Business ID to list stores for |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `stores` | array | List of stores |
| ↳ `externalStoreId` | string | Store ID |
| ↳ `name` | string | Store name |
| ↳ `phoneNumber` | string | Store phone number |
| ↳ `address` | string | Store address |
### `doordash_get_store`
Retrieves details of a specific store.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Parent business ID |
| `externalStoreId` | string | Yes | Store ID to retrieve |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalStoreId` | string | Store ID |
| `name` | string | Store name |
| `phoneNumber` | string | Store phone number |
| `address` | string | Store address |
### `doordash_update_store`
Updates a store location name, phone number, or address.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `developerId` | string | Yes | DoorDash Developer ID |
| `keyId` | string | Yes | No description |
| `signingSecret` | string | Yes | DoorDash Signing Secret |
| `externalBusinessId` | string | Yes | Parent business ID |
| `externalStoreId` | string | Yes | Store ID to update |
| `name` | string | No | Updated store name |
| `phoneNumber` | string | No | Updated phone number |
| `address` | string | No | Updated address |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `externalStoreId` | string | Store ID |
| `name` | string | Store name |
| `phoneNumber` | string | Store phone number |
| `address` | string | Store address |

View File

@@ -29,6 +29,7 @@
"devin",
"discord",
"docusign",
"doordash",
"dropbox",
"dspy",
"dub",
@@ -177,4 +178,4 @@
"zep",
"zoom"
]
}
}

View File

@@ -33,8 +33,9 @@ import {
DatadogIcon,
DevinIcon,
DiscordIcon,
DocumentIcon,
DocuSignIcon,
DocumentIcon,
DoordashIcon,
DropboxIcon,
DsPyIcon,
DubIcon,
@@ -50,8 +51,8 @@ import {
FirecrawlIcon,
FirefliesIcon,
GammaIcon,
GithubIcon,
GitLabIcon,
GithubIcon,
GmailIcon,
GongIcon,
GoogleAdsIcon,
@@ -97,9 +98,9 @@ import {
LinkupIcon,
LoopsIcon,
LumaIcon,
MailServerIcon,
MailchimpIcon,
MailgunIcon,
MailServerIcon,
Mem0Icon,
MicrosoftDataverseIcon,
MicrosoftExcelIcon,
@@ -137,6 +138,8 @@ import {
RevenueCatIcon,
RipplingIcon,
S3Icon,
SQSIcon,
STTIcon,
SalesforceIcon,
SearchIcon,
SendgridIcon,
@@ -148,19 +151,17 @@ import {
SimilarwebIcon,
SlackIcon,
SmtpIcon,
SQSIcon,
SshIcon,
STTIcon,
StagehandIcon,
StripeIcon,
SupabaseIcon,
TTSIcon,
TavilyIcon,
TelegramIcon,
TextractIcon,
TinybirdIcon,
TranslateIcon,
TrelloIcon,
TTSIcon,
TwilioIcon,
TypeformIcon,
UpstashIcon,
@@ -172,11 +173,11 @@ import {
WikipediaIcon,
WordpressIcon,
WorkdayIcon,
xIcon,
YouTubeIcon,
ZendeskIcon,
ZepIcon,
ZoomIcon,
xIcon,
} from '@/components/icons'
type IconComponent = ComponentType<SVGProps<SVGSVGElement>>
@@ -210,6 +211,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
devin: DevinIcon,
discord: DiscordIcon,
docusign: DocuSignIcon,
doordash: DoordashIcon,
dropbox: DropboxIcon,
dspy: DsPyIcon,
dub: DubIcon,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,409 @@
import { createLogger } from '@sim/logger'
import { SignJWT } from 'jose'
import { NextResponse, type NextRequest } from 'next/server'
import { z } from 'zod'
import { checkInternalAuth } from '@/lib/auth/hybrid'
const logger = createLogger('DoordashAPI')
const DOORDASH_BASE_URL = 'https://openapi.doordash.com'
const DRIVE_V2 = `${DOORDASH_BASE_URL}/drive/v2`
const DEVELOPER_V1 = `${DOORDASH_BASE_URL}/developer/v1`
const RequestSchema = z.object({
operation: z.enum([
'create_quote',
'accept_quote',
'create_delivery',
'get_delivery',
'update_delivery',
'cancel_delivery',
'create_business',
'list_businesses',
'update_business',
'create_store',
'list_stores',
'get_store',
'update_store',
]),
developerId: z.string(),
keyId: z.string(),
signingSecret: z.string(),
externalDeliveryId: z.string().optional(),
pickupAddress: z.string().optional(),
pickupPhoneNumber: z.string().optional(),
pickupBusinessName: z.string().optional(),
dropoffAddress: z.string().optional(),
dropoffPhoneNumber: z.string().optional(),
dropoffBusinessName: z.string().optional(),
orderValue: z.string().optional(),
pickupInstructions: z.string().optional(),
dropoffInstructions: z.string().optional(),
tip: z.string().optional(),
dropoffContactSendNotifications: z.string().optional(),
actionIfUndeliverable: z.string().optional(),
contactlessDropoff: z.string().optional(),
dropoffRequiresSignature: z.string().optional(),
dropoffContactGivenName: z.string().optional(),
dropoffContactFamilyName: z.string().optional(),
pickupTime: z.string().optional(),
dropoffTime: z.string().optional(),
externalBusinessId: z.string().optional(),
externalStoreId: z.string().optional(),
name: z.string().optional(),
description: z.string().optional(),
phoneNumber: z.string().optional(),
address: z.string().optional(),
})
/**
* Generates a DoorDash JWT for API authentication.
*/
async function generateJwt(
developerId: string,
keyId: string,
signingSecret: string
): Promise<string> {
const decodedSecret = Buffer.from(signingSecret.replace(/-/g, '+').replace(/_/g, '/'), 'base64')
const now = Math.floor(Date.now() / 1000)
const jwt = await new SignJWT({})
.setProtectedHeader({ alg: 'HS256', typ: 'JWT', kid: keyId, 'dd-ver': 'DD-JWT-V1' })
.setIssuedAt(now)
.setIssuer(developerId)
.setAudience('doordash')
.setExpirationTime(now + 300)
.sign(decodedSecret)
return jwt
}
/**
* Extracts delivery output fields from a DoorDash API response.
*/
function extractDeliveryOutput(data: Record<string, unknown>) {
return {
externalDeliveryId: (data.external_delivery_id as string) ?? '',
deliveryStatus: (data.delivery_status as string) ?? '',
fee: (data.fee as number) ?? null,
tip: (data.tip as number) ?? null,
orderValue: (data.order_value as number) ?? null,
currency: (data.currency as string) ?? null,
trackingUrl: (data.tracking_url as string) ?? null,
supportReference: (data.support_reference as string) ?? null,
dasherName: (data.dasher_name as string) ?? null,
dasherId: (data.dasher_id as number) ?? null,
contactlessDropoff: (data.contactless_dropoff as boolean) ?? null,
dropoffVerificationImageUrl: (data.dropoff_verification_image_url as string) ?? null,
cancellationReason: (data.cancellation_reason as string) ?? null,
pickupTimeEstimated: (data.pickup_time_estimated as string) ?? null,
pickupTimeActual: (data.pickup_time_actual as string) ?? null,
dropoffTimeEstimated: (data.dropoff_time_estimated as string) ?? null,
dropoffTimeActual: (data.dropoff_time_actual as string) ?? null,
pickupAddress: (data.pickup_address as string) ?? null,
dropoffAddress: (data.dropoff_address as string) ?? null,
updatedAt: (data.updated_at as string) ?? null,
}
}
/**
* Extracts business output fields from a DoorDash API response.
*/
function extractBusinessOutput(data: Record<string, unknown>) {
return {
externalBusinessId: (data.external_business_id as string) ?? '',
name: (data.name as string) ?? '',
description: (data.description as string) ?? null,
activationStatus: (data.activation_status as string) ?? null,
}
}
/**
* Extracts store output fields from a DoorDash API response.
*/
function extractStoreOutput(data: Record<string, unknown>) {
return {
externalStoreId: (data.external_store_id as string) ?? '',
name: (data.name as string) ?? '',
phoneNumber: (data.phone_number as string) ?? null,
address: (data.address as string) ?? null,
}
}
export async function POST(request: NextRequest) {
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) {
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
}
let body: z.infer<typeof RequestSchema>
try {
const raw = await request.json()
body = RequestSchema.parse(raw)
} catch (error) {
logger.error('Invalid request body', { error })
return NextResponse.json({ success: false, error: 'Invalid request body' }, { status: 400 })
}
let jwt: string
try {
jwt = await generateJwt(body.developerId, body.keyId, body.signingSecret)
} catch (error) {
logger.error('Failed to generate JWT', { error })
return NextResponse.json(
{ success: false, error: 'Failed to generate DoorDash JWT. Check your credentials.' },
{ status: 400 }
)
}
const headers: Record<string, string> = {
Authorization: `Bearer ${jwt}`,
'Content-Type': 'application/json',
}
try {
let url: string
let method: string
let requestBody: Record<string, unknown> | undefined
switch (body.operation) {
case 'create_quote': {
url = `${DRIVE_V2}/quotes`
method = 'POST'
requestBody = {
external_delivery_id: body.externalDeliveryId?.trim(),
pickup_address: body.pickupAddress,
pickup_phone_number: body.pickupPhoneNumber,
pickup_business_name: body.pickupBusinessName,
dropoff_address: body.dropoffAddress,
dropoff_phone_number: body.dropoffPhoneNumber,
dropoff_business_name: body.dropoffBusinessName,
order_value: Number(body.orderValue),
...(body.pickupInstructions && { pickup_instructions: body.pickupInstructions }),
...(body.dropoffInstructions && { dropoff_instructions: body.dropoffInstructions }),
...(body.tip && { tip: Number(body.tip) }),
...(body.dropoffContactSendNotifications && {
dropoff_contact_send_notifications: body.dropoffContactSendNotifications === 'true',
}),
...(body.actionIfUndeliverable && {
action_if_undeliverable: body.actionIfUndeliverable,
}),
...(body.contactlessDropoff && {
contactless_dropoff: body.contactlessDropoff === 'true',
}),
...(body.dropoffRequiresSignature && {
dropoff_requires_signature: body.dropoffRequiresSignature === 'true',
}),
...(body.dropoffContactGivenName && {
dropoff_contact_given_name: body.dropoffContactGivenName,
}),
...(body.dropoffContactFamilyName && {
dropoff_contact_family_name: body.dropoffContactFamilyName,
}),
...(body.pickupTime && { pickup_time: body.pickupTime }),
...(body.dropoffTime && { dropoff_time: body.dropoffTime }),
}
break
}
case 'accept_quote': {
url = `${DRIVE_V2}/quotes/${encodeURIComponent(body.externalDeliveryId?.trim() ?? '')}/accept`
method = 'POST'
requestBody = {
...(body.tip && { tip: Number(body.tip) }),
...(body.dropoffPhoneNumber && { dropoff_phone_number: body.dropoffPhoneNumber }),
}
break
}
case 'create_delivery': {
url = `${DRIVE_V2}/deliveries`
method = 'POST'
requestBody = {
external_delivery_id: body.externalDeliveryId?.trim(),
pickup_address: body.pickupAddress,
pickup_phone_number: body.pickupPhoneNumber,
pickup_business_name: body.pickupBusinessName,
dropoff_address: body.dropoffAddress,
dropoff_phone_number: body.dropoffPhoneNumber,
dropoff_business_name: body.dropoffBusinessName,
order_value: Number(body.orderValue),
...(body.pickupInstructions && { pickup_instructions: body.pickupInstructions }),
...(body.dropoffInstructions && { dropoff_instructions: body.dropoffInstructions }),
...(body.tip && { tip: Number(body.tip) }),
...(body.dropoffContactSendNotifications && {
dropoff_contact_send_notifications: body.dropoffContactSendNotifications === 'true',
}),
...(body.actionIfUndeliverable && {
action_if_undeliverable: body.actionIfUndeliverable,
}),
...(body.contactlessDropoff && {
contactless_dropoff: body.contactlessDropoff === 'true',
}),
...(body.dropoffRequiresSignature && {
dropoff_requires_signature: body.dropoffRequiresSignature === 'true',
}),
...(body.dropoffContactGivenName && {
dropoff_contact_given_name: body.dropoffContactGivenName,
}),
...(body.dropoffContactFamilyName && {
dropoff_contact_family_name: body.dropoffContactFamilyName,
}),
...(body.pickupTime && { pickup_time: body.pickupTime }),
...(body.dropoffTime && { dropoff_time: body.dropoffTime }),
}
break
}
case 'get_delivery': {
url = `${DRIVE_V2}/deliveries/${encodeURIComponent(body.externalDeliveryId?.trim() ?? '')}`
method = 'GET'
break
}
case 'update_delivery': {
url = `${DRIVE_V2}/deliveries/${encodeURIComponent(body.externalDeliveryId?.trim() ?? '')}`
method = 'PATCH'
requestBody = {
...(body.tip && { tip: Number(body.tip) }),
...(body.dropoffPhoneNumber && { dropoff_phone_number: body.dropoffPhoneNumber }),
...(body.dropoffInstructions && { dropoff_instructions: body.dropoffInstructions }),
}
break
}
case 'cancel_delivery': {
url = `${DRIVE_V2}/deliveries/${encodeURIComponent(body.externalDeliveryId?.trim() ?? '')}/cancel`
method = 'PUT'
requestBody = {}
break
}
case 'create_business': {
url = `${DEVELOPER_V1}/businesses`
method = 'POST'
requestBody = {
external_business_id: body.externalBusinessId?.trim(),
name: body.name,
...(body.description && { description: body.description }),
}
break
}
case 'list_businesses': {
url = `${DEVELOPER_V1}/businesses`
method = 'GET'
break
}
case 'update_business': {
url = `${DEVELOPER_V1}/businesses/${encodeURIComponent(body.externalBusinessId?.trim() ?? '')}`
method = 'PATCH'
requestBody = {
...(body.name && { name: body.name }),
...(body.description && { description: body.description }),
}
break
}
case 'create_store': {
url = `${DEVELOPER_V1}/businesses/${encodeURIComponent(body.externalBusinessId?.trim() ?? '')}/stores`
method = 'POST'
requestBody = {
external_store_id: body.externalStoreId?.trim(),
name: body.name,
phone_number: body.phoneNumber,
address: body.address,
}
break
}
case 'list_stores': {
url = `${DEVELOPER_V1}/businesses/${encodeURIComponent(body.externalBusinessId?.trim() ?? '')}/stores`
method = 'GET'
break
}
case 'get_store': {
url = `${DEVELOPER_V1}/businesses/${encodeURIComponent(body.externalBusinessId?.trim() ?? '')}/stores/${encodeURIComponent(body.externalStoreId?.trim() ?? '')}`
method = 'GET'
break
}
case 'update_store': {
url = `${DEVELOPER_V1}/businesses/${encodeURIComponent(body.externalBusinessId?.trim() ?? '')}/stores/${encodeURIComponent(body.externalStoreId?.trim() ?? '')}`
method = 'PATCH'
requestBody = {
...(body.name && { name: body.name }),
...(body.phoneNumber && { phone_number: body.phoneNumber }),
...(body.address && { address: body.address }),
}
break
}
}
const fetchOptions: RequestInit = {
method,
headers,
...(requestBody && { body: JSON.stringify(requestBody) }),
}
const response = await fetch(url, fetchOptions)
const data = await response.json()
if (!response.ok) {
const errorMessage =
(data as Record<string, unknown>).message ??
(data as Record<string, unknown>).error ??
`DoorDash API error (${response.status})`
logger.error('DoorDash API error', { status: response.status, error: errorMessage })
return NextResponse.json(
{ success: false, error: String(errorMessage) },
{ status: response.status }
)
}
let output: Record<string, unknown>
switch (body.operation) {
case 'list_businesses': {
const results = Array.isArray(data) ? data : (data as Record<string, unknown>).result ?? []
output = {
businesses: (results as Record<string, unknown>[]).map(extractBusinessOutput),
}
break
}
case 'create_business':
case 'update_business': {
output = extractBusinessOutput(data as Record<string, unknown>)
break
}
case 'list_stores': {
const results = Array.isArray(data) ? data : (data as Record<string, unknown>).result ?? []
output = {
stores: (results as Record<string, unknown>[]).map(extractStoreOutput),
}
break
}
case 'create_store':
case 'get_store':
case 'update_store': {
output = extractStoreOutput(data as Record<string, unknown>)
break
}
default: {
output = extractDeliveryOutput(data as Record<string, unknown>)
break
}
}
return NextResponse.json({ success: true, output })
} catch (error) {
logger.error('DoorDash API request failed', { error })
return NextResponse.json(
{ success: false, error: 'Failed to communicate with DoorDash API' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,475 @@
import { DoordashIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import { AuthMode, IntegrationType } from '@/blocks/types'
import type { DoordashDeliveryResponse } from '@/tools/doordash/types'
export const DoordashBlock: BlockConfig<DoordashDeliveryResponse> = {
type: 'doordash',
name: 'DoorDash',
description: 'Create and manage DoorDash Drive deliveries, businesses, and stores',
longDescription:
'Integrate DoorDash Drive into workflows. Create delivery quotes, accept quotes, create deliveries, track status, update details, cancel deliveries, and manage businesses and store locations.',
docsLink: 'https://docs.sim.ai/tools/doordash',
category: 'tools',
integrationType: IntegrationType.Ecommerce,
tags: ['automation'],
bgColor: '#FF3008',
icon: DoordashIcon,
authMode: AuthMode.ApiKey,
subBlocks: [
{
id: 'operation',
title: 'Operation',
type: 'dropdown',
options: [
{ label: 'Create Quote', id: 'create_quote' },
{ label: 'Accept Quote', id: 'accept_quote' },
{ label: 'Create Delivery', id: 'create_delivery' },
{ label: 'Get Delivery', id: 'get_delivery' },
{ label: 'Update Delivery', id: 'update_delivery' },
{ label: 'Cancel Delivery', id: 'cancel_delivery' },
{ label: 'Create Business', id: 'create_business' },
{ label: 'List Businesses', id: 'list_businesses' },
{ label: 'Update Business', id: 'update_business' },
{ label: 'Create Store', id: 'create_store' },
{ label: 'List Stores', id: 'list_stores' },
{ label: 'Get Store', id: 'get_store' },
{ label: 'Update Store', id: 'update_store' },
],
value: () => 'create_quote',
},
// Credentials (common to all operations)
{
id: 'developerId',
title: 'Developer ID',
type: 'short-input',
placeholder: 'Enter your DoorDash Developer ID',
password: true,
required: true,
},
{
id: 'keyId',
title: 'Key ID',
type: 'short-input',
placeholder: 'Enter your DoorDash Key ID',
password: true,
required: true,
},
{
id: 'signingSecret',
title: 'Signing Secret',
type: 'short-input',
placeholder: 'Enter your DoorDash Signing Secret',
password: true,
required: true,
},
// Delivery ID (delivery operations only)
{
id: 'externalDeliveryId',
title: 'External Delivery ID',
type: 'short-input',
placeholder: 'Unique delivery identifier (e.g., D-12345)',
required: {
field: 'operation',
value: [
'create_quote',
'accept_quote',
'create_delivery',
'get_delivery',
'update_delivery',
'cancel_delivery',
],
},
condition: {
field: 'operation',
value: [
'create_quote',
'accept_quote',
'create_delivery',
'get_delivery',
'update_delivery',
'cancel_delivery',
],
},
},
// Pickup fields (create_quote and create_delivery)
{
id: 'pickupAddress',
title: 'Pickup Address',
type: 'short-input',
placeholder: '901 Market Street, San Francisco, CA 94103',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'pickupPhoneNumber',
title: 'Pickup Phone',
type: 'short-input',
placeholder: '+16505555555',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'pickupBusinessName',
title: 'Pickup Business Name',
type: 'short-input',
placeholder: 'Business name at pickup',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
// Dropoff fields (create_quote and create_delivery)
{
id: 'dropoffAddress',
title: 'Dropoff Address',
type: 'short-input',
placeholder: '123 Main Street, San Francisco, CA 94105',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'dropoffPhoneNumber',
title: 'Dropoff Phone',
type: 'short-input',
placeholder: '+16505555555',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: {
field: 'operation',
value: ['create_quote', 'create_delivery', 'accept_quote', 'update_delivery'],
},
},
{
id: 'dropoffBusinessName',
title: 'Dropoff Contact Name',
type: 'short-input',
placeholder: 'Recipient name or business',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
// Order value (create_quote and create_delivery)
{
id: 'orderValue',
title: 'Order Value (cents)',
type: 'short-input',
placeholder: '1999 (for $19.99)',
required: { field: 'operation', value: ['create_quote', 'create_delivery'] },
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
// Recipient name fields (advanced, create_quote/create_delivery)
{
id: 'dropoffContactGivenName',
title: 'Recipient First Name',
type: 'short-input',
placeholder: 'Customer first name',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'dropoffContactFamilyName',
title: 'Recipient Last Name',
type: 'short-input',
placeholder: 'Customer last name',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
// Optional delivery fields
{
id: 'pickupInstructions',
title: 'Pickup Instructions',
type: 'short-input',
placeholder: 'Instructions for the Dasher at pickup',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'dropoffInstructions',
title: 'Dropoff Instructions',
type: 'short-input',
placeholder: 'Instructions for the Dasher at dropoff',
mode: 'advanced',
condition: {
field: 'operation',
value: ['create_quote', 'create_delivery', 'update_delivery'],
},
},
{
id: 'tip',
title: 'Tip (cents)',
type: 'short-input',
placeholder: '500 (for $5.00)',
mode: 'advanced',
condition: {
field: 'operation',
value: ['create_quote', 'create_delivery', 'accept_quote', 'update_delivery'],
},
},
{
id: 'pickupTime',
title: 'Scheduled Pickup Time',
type: 'short-input',
placeholder: 'ISO 8601 (e.g., 2025-01-15T14:00:00Z)',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
wandConfig: {
enabled: true,
prompt: `Generate an ISO 8601 timestamp for the requested pickup time. Return ONLY the timestamp string - no explanations, no extra text.`,
placeholder: 'Describe when to pick up (e.g., "in 2 hours", "tomorrow at 3pm")...',
generationType: 'timestamp',
},
},
{
id: 'dropoffTime',
title: 'Scheduled Dropoff Time',
type: 'short-input',
placeholder: 'ISO 8601 (e.g., 2025-01-15T15:00:00Z)',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
wandConfig: {
enabled: true,
prompt: `Generate an ISO 8601 timestamp for the requested dropoff time. Return ONLY the timestamp string - no explanations, no extra text.`,
placeholder: 'Describe when to deliver (e.g., "by 5pm", "in 3 hours")...',
generationType: 'timestamp',
},
},
{
id: 'contactlessDropoff',
title: 'Contactless Dropoff',
type: 'dropdown',
options: [
{ label: 'No', id: '' },
{ label: 'Yes', id: 'true' },
],
value: () => '',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'dropoffRequiresSignature',
title: 'Require Signature',
type: 'dropdown',
options: [
{ label: 'No', id: '' },
{ label: 'Yes', id: 'true' },
],
value: () => '',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'dropoffContactSendNotifications',
title: 'Send SMS Notifications',
type: 'dropdown',
options: [
{ label: 'Yes', id: 'true' },
{ label: 'No', id: 'false' },
],
value: () => 'true',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
{
id: 'actionIfUndeliverable',
title: 'If Undeliverable',
type: 'dropdown',
options: [
{ label: 'Default', id: '' },
{ label: 'Return to Pickup', id: 'return_to_pickup' },
],
value: () => '',
mode: 'advanced',
condition: { field: 'operation', value: ['create_quote', 'create_delivery'] },
},
// Business fields
{
id: 'externalBusinessId',
title: 'Business ID',
type: 'short-input',
placeholder: 'Unique business identifier',
required: {
field: 'operation',
value: [
'create_business',
'update_business',
'create_store',
'list_stores',
'get_store',
'update_store',
],
},
condition: {
field: 'operation',
value: [
'create_business',
'update_business',
'create_store',
'list_stores',
'get_store',
'update_store',
],
},
},
{
id: 'name',
title: 'Name',
type: 'short-input',
placeholder: 'Business or store name',
required: {
field: 'operation',
value: ['create_business', 'create_store'],
},
condition: {
field: 'operation',
value: ['create_business', 'update_business', 'create_store', 'update_store'],
},
},
{
id: 'description',
title: 'Description',
type: 'short-input',
placeholder: 'Business description',
mode: 'advanced',
condition: {
field: 'operation',
value: ['create_business', 'update_business'],
},
},
// Store fields
{
id: 'externalStoreId',
title: 'Store ID',
type: 'short-input',
placeholder: 'Unique store identifier',
required: {
field: 'operation',
value: ['create_store', 'get_store', 'update_store'],
},
condition: {
field: 'operation',
value: ['create_store', 'get_store', 'update_store'],
},
},
{
id: 'phoneNumber',
title: 'Store Phone',
type: 'short-input',
placeholder: '+16505555555',
required: { field: 'operation', value: 'create_store' },
condition: {
field: 'operation',
value: ['create_store', 'update_store'],
},
},
{
id: 'address',
title: 'Store Address',
type: 'short-input',
placeholder: '901 Market Street, San Francisco, CA 94103',
required: { field: 'operation', value: 'create_store' },
condition: {
field: 'operation',
value: ['create_store', 'update_store'],
},
},
],
tools: {
access: [
'doordash_create_quote',
'doordash_accept_quote',
'doordash_create_delivery',
'doordash_get_delivery',
'doordash_update_delivery',
'doordash_cancel_delivery',
'doordash_create_business',
'doordash_list_businesses',
'doordash_update_business',
'doordash_create_store',
'doordash_list_stores',
'doordash_get_store',
'doordash_update_store',
],
config: {
tool: (params) => `doordash_${params.operation}`,
params: (params) => {
const result: Record<string, unknown> = {}
if (params.orderValue) result.orderValue = String(params.orderValue)
if (params.tip) result.tip = String(params.tip)
if (params.actionIfUndeliverable === '') result.actionIfUndeliverable = undefined
if (params.contactlessDropoff === '') result.contactlessDropoff = undefined
if (params.dropoffRequiresSignature === '') result.dropoffRequiresSignature = undefined
return result
},
},
},
inputs: {
operation: { type: 'string', description: 'Operation to perform' },
developerId: { type: 'string', description: 'DoorDash Developer ID' },
keyId: { type: 'string', description: 'DoorDash Key ID' },
signingSecret: { type: 'string', description: 'DoorDash Signing Secret' },
externalDeliveryId: { type: 'string', description: 'Unique delivery identifier' },
pickupAddress: { type: 'string', description: 'Pickup address' },
pickupPhoneNumber: { type: 'string', description: 'Pickup phone number' },
pickupBusinessName: { type: 'string', description: 'Pickup business name' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
dropoffPhoneNumber: { type: 'string', description: 'Dropoff phone number' },
dropoffBusinessName: { type: 'string', description: 'Dropoff contact name' },
orderValue: { type: 'string', description: 'Order value in cents' },
dropoffContactGivenName: { type: 'string', description: 'Recipient first name' },
dropoffContactFamilyName: { type: 'string', description: 'Recipient last name' },
pickupInstructions: { type: 'string', description: 'Pickup instructions' },
dropoffInstructions: { type: 'string', description: 'Dropoff instructions' },
tip: { type: 'string', description: 'Tip amount in cents' },
pickupTime: { type: 'string', description: 'Scheduled pickup time (ISO 8601)' },
dropoffTime: { type: 'string', description: 'Scheduled dropoff time (ISO 8601)' },
contactlessDropoff: { type: 'string', description: 'Contactless dropoff' },
dropoffRequiresSignature: { type: 'string', description: 'Require signature' },
dropoffContactSendNotifications: { type: 'string', description: 'Send SMS notifications' },
actionIfUndeliverable: { type: 'string', description: 'Action if undeliverable' },
externalBusinessId: { type: 'string', description: 'Business ID' },
name: { type: 'string', description: 'Business or store name' },
description: { type: 'string', description: 'Business description' },
externalStoreId: { type: 'string', description: 'Store ID' },
phoneNumber: { type: 'string', description: 'Store phone number' },
address: { type: 'string', description: 'Store address' },
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents' },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name' },
dasherId: { type: 'number', description: 'Assigned Dasher ID' },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used' },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL' },
cancellationReason: { type: 'string', description: 'Reason for cancellation' },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
pickupTimeActual: { type: 'string', description: 'Actual pickup time' },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
dropoffTimeActual: { type: 'string', description: 'Actual dropoff time' },
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp' },
externalBusinessId: { type: 'string', description: 'Business ID' },
externalStoreId: { type: 'string', description: 'Store ID' },
name: { type: 'string', description: 'Business or store name' },
businesses: {
type: 'json',
description: 'List of businesses (externalBusinessId, name, description, activationStatus)',
},
stores: {
type: 'json',
description: 'List of stores (externalStoreId, name, phoneNumber, address)',
},
},
}

View File

@@ -31,6 +31,7 @@ import { DatadogBlock } from '@/blocks/blocks/datadog'
import { DevinBlock } from '@/blocks/blocks/devin'
import { DiscordBlock } from '@/blocks/blocks/discord'
import { DocuSignBlock } from '@/blocks/blocks/docusign'
import { DoordashBlock } from '@/blocks/blocks/doordash'
import { DropboxBlock } from '@/blocks/blocks/dropbox'
import { DSPyBlock } from '@/blocks/blocks/dspy'
import { DubBlock } from '@/blocks/blocks/dub'
@@ -244,6 +245,7 @@ export const registry: Record<string, BlockConfig> = {
devin: DevinBlock,
discord: DiscordBlock,
docusign: DocuSignBlock,
doordash: DoordashBlock,
dropbox: DropboxBlock,
dspy: DSPyBlock,
dub: DubBlock,

View File

@@ -1193,6 +1193,18 @@ export function DocuSignIcon(props: SVGProps<SVGSVGElement>) {
)
}
export function DoordashIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 132 75' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='132' height='75' rx='8' fill='white' />
<path
d='M126.9 17.8C121 6.8 109.6 0 97.2 0H3.2C1.4 0 0 1.5 0 3.3c0 .8.3 1.7.9 2.3l20.5 20.6c1.8 1.8 4.3 2.8 6.8 2.8h66.3c4.7 0 8.6 3.7 8.6 8.5 0 4.7-3.7 8.6-8.5 8.6H49c-1.8 0-3.2 1.5-3.2 3.3 0 .9.3 1.7.9 2.3l20.5 20.6C69 74 71.5 75 74 75h20.7c26.9 0 47.2-28.7 32.2-57.2'
fill='#FF3008'
/>
</svg>
)
}
export function DiscordIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg

View File

@@ -0,0 +1,121 @@
import type { DoordashAcceptQuoteParams, DoordashDeliveryResponse } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const acceptQuoteTool: ToolConfig<DoordashAcceptQuoteParams, DoordashDeliveryResponse> = {
id: 'doordash_accept_quote',
name: 'DoorDash Accept Quote',
description:
'Accepts a delivery quote to formally create the delivery. Must be called within 5 minutes of creating the quote.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'External delivery ID from the quote',
},
tip: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Tip amount in cents',
},
dropoffPhoneNumber: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated dropoff phone number',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'accept_quote',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
tip: params.tip,
dropoffPhoneNumber: params.dropoffPhoneNumber,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to accept quote' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
fee: data.output.fee ?? null,
tip: data.output.tip ?? null,
orderValue: data.output.orderValue ?? null,
currency: data.output.currency ?? null,
trackingUrl: data.output.trackingUrl ?? null,
supportReference: data.output.supportReference ?? null,
dasherName: data.output.dasherName ?? null,
dasherId: data.output.dasherId ?? null,
contactlessDropoff: data.output.contactlessDropoff ?? null,
dropoffVerificationImageUrl: data.output.dropoffVerificationImageUrl ?? null,
cancellationReason: data.output.cancellationReason ?? null,
pickupTimeEstimated: data.output.pickupTimeEstimated ?? null,
pickupTimeActual: data.output.pickupTimeActual ?? null,
dropoffTimeEstimated: data.output.dropoffTimeEstimated ?? null,
dropoffTimeActual: data.output.dropoffTimeActual ?? null,
pickupAddress: data.output.pickupAddress ?? null,
dropoffAddress: data.output.dropoffAddress ?? null,
updatedAt: data.output.updatedAt ?? null,
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents', optional: true },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name', optional: true },
dasherId: { type: 'number', description: 'Assigned Dasher ID', optional: true },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used', optional: true },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL at dropoff', optional: true },
cancellationReason: { type: 'string', description: 'Reason for cancellation', optional: true },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
pickupTimeActual: { type: 'string', description: 'Actual pickup time', optional: true },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
dropoffTimeActual: { type: 'string', description: 'Actual dropoff time', optional: true },
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
},
}

View File

@@ -0,0 +1,77 @@
import type {
DoordashCancelDeliveryParams,
DoordashCancelResponse,
} from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const cancelDeliveryTool: ToolConfig<
DoordashCancelDeliveryParams,
DoordashCancelResponse
> = {
id: 'doordash_cancel_delivery',
name: 'DoorDash Cancel Delivery',
description:
'Cancels a delivery. Cannot be used after a Dasher has been assigned to the delivery.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'External delivery ID to cancel',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'cancel_delivery',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to cancel delivery' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status (cancelled)' },
},
}

View File

@@ -0,0 +1,76 @@
import type { DoordashBusinessResponse, DoordashCreateBusinessParams } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const createBusinessTool: ToolConfig<DoordashCreateBusinessParams, DoordashBusinessResponse> = {
id: 'doordash_create_business',
name: 'DoorDash Create Business',
description: 'Creates a new business entity for organizing delivery locations.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique business identifier',
},
name: { type: 'string', required: true, visibility: 'user-or-llm', description: 'Business name' },
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Business description',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'create_business',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
name: params.name,
description: params.description,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to create business' } }
}
return {
success: true,
output: {
externalBusinessId: data.output.externalBusinessId ?? '',
name: data.output.name ?? '',
description: data.output.description ?? null,
activationStatus: data.output.activationStatus ?? null,
},
}
},
outputs: {
externalBusinessId: { type: 'string', description: 'Business ID' },
name: { type: 'string', description: 'Business name' },
description: { type: 'string', description: 'Business description', optional: true },
activationStatus: { type: 'string', description: 'Activation status', optional: true },
},
}

View File

@@ -0,0 +1,238 @@
import type {
DoordashCreateDeliveryParams,
DoordashDeliveryResponse,
} from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const createDeliveryTool: ToolConfig<
DoordashCreateDeliveryParams,
DoordashDeliveryResponse
> = {
id: 'doordash_create_delivery',
name: 'DoorDash Create Delivery',
description: 'Creates a delivery directly without a prior quote. Skips price confirmation.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique delivery identifier',
},
pickupAddress: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup address (e.g., "901 Market Street 6th Floor San Francisco, CA 94103")',
},
pickupPhoneNumber: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup phone number (e.g., "+16505555555")',
},
pickupBusinessName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup business name',
},
dropoffAddress: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff address',
},
dropoffPhoneNumber: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff phone number',
},
dropoffBusinessName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff contact or business name',
},
orderValue: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Order value in cents (e.g., "1999" for $19.99)',
},
pickupInstructions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Instructions for pickup',
},
dropoffInstructions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Instructions for dropoff',
},
tip: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Tip amount in cents',
},
dropoffContactSendNotifications: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Send SMS notifications to recipient (true/false)',
},
actionIfUndeliverable: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Action if undeliverable (e.g., "return_to_pickup")',
},
contactlessDropoff: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Contactless doorstep delivery with photo verification (true/false)',
},
dropoffRequiresSignature: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Require signature at dropoff (true/false)',
},
dropoffContactGivenName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Recipient first name',
},
dropoffContactFamilyName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Recipient last name',
},
pickupTime: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Scheduled pickup time (ISO 8601, mutually exclusive with dropoffTime)',
},
dropoffTime: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Scheduled dropoff time (ISO 8601, mutually exclusive with pickupTime)',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'create_delivery',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
pickupAddress: params.pickupAddress,
pickupPhoneNumber: params.pickupPhoneNumber,
pickupBusinessName: params.pickupBusinessName,
dropoffAddress: params.dropoffAddress,
dropoffPhoneNumber: params.dropoffPhoneNumber,
dropoffBusinessName: params.dropoffBusinessName,
orderValue: params.orderValue,
pickupInstructions: params.pickupInstructions,
dropoffInstructions: params.dropoffInstructions,
tip: params.tip,
dropoffContactSendNotifications: params.dropoffContactSendNotifications,
actionIfUndeliverable: params.actionIfUndeliverable,
contactlessDropoff: params.contactlessDropoff,
dropoffRequiresSignature: params.dropoffRequiresSignature,
dropoffContactGivenName: params.dropoffContactGivenName,
dropoffContactFamilyName: params.dropoffContactFamilyName,
pickupTime: params.pickupTime,
dropoffTime: params.dropoffTime,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to create delivery' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
fee: data.output.fee ?? null,
tip: data.output.tip ?? null,
orderValue: data.output.orderValue ?? null,
currency: data.output.currency ?? null,
trackingUrl: data.output.trackingUrl ?? null,
supportReference: data.output.supportReference ?? null,
dasherName: data.output.dasherName ?? null,
dasherId: data.output.dasherId ?? null,
contactlessDropoff: data.output.contactlessDropoff ?? null,
dropoffVerificationImageUrl: data.output.dropoffVerificationImageUrl ?? null,
cancellationReason: data.output.cancellationReason ?? null,
pickupTimeEstimated: data.output.pickupTimeEstimated ?? null,
pickupTimeActual: data.output.pickupTimeActual ?? null,
dropoffTimeEstimated: data.output.dropoffTimeEstimated ?? null,
dropoffTimeActual: data.output.dropoffTimeActual ?? null,
pickupAddress: data.output.pickupAddress ?? null,
dropoffAddress: data.output.dropoffAddress ?? null,
updatedAt: data.output.updatedAt ?? null,
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents', optional: true },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name', optional: true },
dasherId: { type: 'number', description: 'Assigned Dasher ID', optional: true },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used', optional: true },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL at dropoff', optional: true },
cancellationReason: { type: 'string', description: 'Reason for cancellation', optional: true },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
pickupTimeActual: { type: 'string', description: 'Actual pickup time', optional: true },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
dropoffTimeActual: { type: 'string', description: 'Actual dropoff time', optional: true },
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
},
}

View File

@@ -0,0 +1,205 @@
import type { DoordashCreateQuoteParams, DoordashQuoteResponse } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const createQuoteTool: ToolConfig<DoordashCreateQuoteParams, DoordashQuoteResponse> = {
id: 'doordash_create_quote',
name: 'DoorDash Create Quote',
description:
'Creates a delivery quote to validate coverage, pricing, and estimated delivery times.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique delivery identifier',
},
pickupAddress: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup address (e.g., "901 Market Street 6th Floor San Francisco, CA 94103")',
},
pickupPhoneNumber: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup phone number (e.g., "+16505555555")',
},
pickupBusinessName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Pickup business name',
},
dropoffAddress: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff address',
},
dropoffPhoneNumber: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff phone number',
},
dropoffBusinessName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Dropoff contact or business name',
},
orderValue: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Order value in cents (e.g., "1999" for $19.99)',
},
pickupInstructions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Instructions for pickup',
},
dropoffInstructions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Instructions for dropoff',
},
tip: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Tip amount in cents',
},
dropoffContactSendNotifications: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Send SMS notifications to recipient (true/false)',
},
actionIfUndeliverable: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Action if undeliverable (e.g., "return_to_pickup")',
},
contactlessDropoff: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Contactless doorstep delivery with photo verification (true/false)',
},
dropoffRequiresSignature: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Require signature at dropoff (true/false)',
},
dropoffContactGivenName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Recipient first name',
},
dropoffContactFamilyName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Recipient last name',
},
pickupTime: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Scheduled pickup time (ISO 8601, mutually exclusive with dropoffTime)',
},
dropoffTime: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Scheduled dropoff time (ISO 8601, mutually exclusive with pickupTime)',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'create_quote',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
pickupAddress: params.pickupAddress,
pickupPhoneNumber: params.pickupPhoneNumber,
pickupBusinessName: params.pickupBusinessName,
dropoffAddress: params.dropoffAddress,
dropoffPhoneNumber: params.dropoffPhoneNumber,
dropoffBusinessName: params.dropoffBusinessName,
orderValue: params.orderValue,
pickupInstructions: params.pickupInstructions,
dropoffInstructions: params.dropoffInstructions,
tip: params.tip,
dropoffContactSendNotifications: params.dropoffContactSendNotifications,
actionIfUndeliverable: params.actionIfUndeliverable,
contactlessDropoff: params.contactlessDropoff,
dropoffRequiresSignature: params.dropoffRequiresSignature,
dropoffContactGivenName: params.dropoffContactGivenName,
dropoffContactFamilyName: params.dropoffContactFamilyName,
pickupTime: params.pickupTime,
dropoffTime: params.dropoffTime,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to create quote' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
fee: data.output.fee ?? null,
currency: data.output.currency ?? null,
pickupTimeEstimated: data.output.pickupTimeEstimated ?? null,
dropoffTimeEstimated: data.output.dropoffTimeEstimated ?? null,
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
currency: { type: 'string', description: 'Fee currency code' },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
},
}

View File

@@ -0,0 +1,85 @@
import type { DoordashCreateStoreParams, DoordashStoreResponse } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const createStoreTool: ToolConfig<DoordashCreateStoreParams, DoordashStoreResponse> = {
id: 'doordash_create_store',
name: 'DoorDash Create Store',
description: 'Creates a store location under a business for delivery pickup.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Parent business ID',
},
externalStoreId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Unique store identifier',
},
name: { type: 'string', required: true, visibility: 'user-or-llm', description: 'Store name' },
phoneNumber: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Store phone number',
},
address: { type: 'string', required: true, visibility: 'user-or-llm', description: 'Store address' },
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'create_store',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
externalStoreId: params.externalStoreId,
name: params.name,
phoneNumber: params.phoneNumber,
address: params.address,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to create store' } }
}
return {
success: true,
output: {
externalStoreId: data.output.externalStoreId ?? '',
name: data.output.name ?? '',
phoneNumber: data.output.phoneNumber ?? null,
address: data.output.address ?? null,
},
}
},
outputs: {
externalStoreId: { type: 'string', description: 'Store ID' },
name: { type: 'string', description: 'Store name' },
phoneNumber: { type: 'string', description: 'Store phone number' },
address: { type: 'string', description: 'Store address' },
},
}

View File

@@ -0,0 +1,106 @@
import type { DoordashDeliveryResponse, DoordashGetDeliveryParams } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const getDeliveryTool: ToolConfig<DoordashGetDeliveryParams, DoordashDeliveryResponse> = {
id: 'doordash_get_delivery',
name: 'DoorDash Get Delivery',
description: 'Retrieves the current status and details of a delivery.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'External delivery ID to look up',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'get_delivery',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to get delivery' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
fee: data.output.fee ?? null,
tip: data.output.tip ?? null,
orderValue: data.output.orderValue ?? null,
currency: data.output.currency ?? null,
trackingUrl: data.output.trackingUrl ?? null,
supportReference: data.output.supportReference ?? null,
dasherName: data.output.dasherName ?? null,
dasherId: data.output.dasherId ?? null,
contactlessDropoff: data.output.contactlessDropoff ?? null,
dropoffVerificationImageUrl: data.output.dropoffVerificationImageUrl ?? null,
cancellationReason: data.output.cancellationReason ?? null,
pickupTimeEstimated: data.output.pickupTimeEstimated ?? null,
pickupTimeActual: data.output.pickupTimeActual ?? null,
dropoffTimeEstimated: data.output.dropoffTimeEstimated ?? null,
dropoffTimeActual: data.output.dropoffTimeActual ?? null,
pickupAddress: data.output.pickupAddress ?? null,
dropoffAddress: data.output.dropoffAddress ?? null,
updatedAt: data.output.updatedAt ?? null,
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents', optional: true },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name', optional: true },
dasherId: { type: 'number', description: 'Assigned Dasher ID', optional: true },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used', optional: true },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL at dropoff', optional: true },
cancellationReason: { type: 'string', description: 'Reason for cancellation', optional: true },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
pickupTimeActual: { type: 'string', description: 'Actual pickup time', optional: true },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
dropoffTimeActual: { type: 'string', description: 'Actual dropoff time', optional: true },
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
},
}

View File

@@ -0,0 +1,74 @@
import type { DoordashGetStoreParams, DoordashStoreResponse } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const getStoreTool: ToolConfig<DoordashGetStoreParams, DoordashStoreResponse> = {
id: 'doordash_get_store',
name: 'DoorDash Get Store',
description: 'Retrieves details of a specific store.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Parent business ID',
},
externalStoreId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Store ID to retrieve',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'get_store',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
externalStoreId: params.externalStoreId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to get store' } }
}
return {
success: true,
output: {
externalStoreId: data.output.externalStoreId ?? '',
name: data.output.name ?? '',
phoneNumber: data.output.phoneNumber ?? null,
address: data.output.address ?? null,
},
}
},
outputs: {
externalStoreId: { type: 'string', description: 'Store ID' },
name: { type: 'string', description: 'Store name' },
phoneNumber: { type: 'string', description: 'Store phone number' },
address: { type: 'string', description: 'Store address' },
},
}

View File

@@ -0,0 +1,51 @@
import { acceptQuoteTool } from '@/tools/doordash/accept_quote'
import { cancelDeliveryTool } from '@/tools/doordash/cancel_delivery'
import { createBusinessTool } from '@/tools/doordash/create_business'
import { createDeliveryTool } from '@/tools/doordash/create_delivery'
import { createQuoteTool } from '@/tools/doordash/create_quote'
import { createStoreTool } from '@/tools/doordash/create_store'
import { getDeliveryTool } from '@/tools/doordash/get_delivery'
import { getStoreTool } from '@/tools/doordash/get_store'
import { listBusinessesTool } from '@/tools/doordash/list_businesses'
import { listStoresTool } from '@/tools/doordash/list_stores'
import { updateBusinessTool } from '@/tools/doordash/update_business'
import { updateDeliveryTool } from '@/tools/doordash/update_delivery'
import { updateStoreTool } from '@/tools/doordash/update_store'
export const doordashAcceptQuoteTool = acceptQuoteTool
export const doordashCancelDeliveryTool = cancelDeliveryTool
export const doordashCreateBusinessTool = createBusinessTool
export const doordashCreateDeliveryTool = createDeliveryTool
export const doordashCreateQuoteTool = createQuoteTool
export const doordashCreateStoreTool = createStoreTool
export const doordashGetDeliveryTool = getDeliveryTool
export const doordashGetStoreTool = getStoreTool
export const doordashListBusinessesTool = listBusinessesTool
export const doordashListStoresTool = listStoresTool
export const doordashUpdateBusinessTool = updateBusinessTool
export const doordashUpdateDeliveryTool = updateDeliveryTool
export const doordashUpdateStoreTool = updateStoreTool
export type {
DoordashAcceptQuoteParams,
DoordashBaseParams,
DoordashBusinessListResponse,
DoordashBusinessResponse,
DoordashCancelDeliveryParams,
DoordashCancelResponse,
DoordashCreateBusinessParams,
DoordashCreateDeliveryParams,
DoordashCreateQuoteParams,
DoordashCreateStoreParams,
DoordashDeliveryResponse,
DoordashGetDeliveryParams,
DoordashGetStoreParams,
DoordashListBusinessesParams,
DoordashListStoresParams,
DoordashQuoteResponse,
DoordashStoreListResponse,
DoordashStoreResponse,
DoordashUpdateBusinessParams,
DoordashUpdateDeliveryParams,
DoordashUpdateStoreParams,
} from '@/tools/doordash/types'

View File

@@ -0,0 +1,64 @@
import type { DoordashBusinessListResponse, DoordashListBusinessesParams } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const listBusinessesTool: ToolConfig<
DoordashListBusinessesParams,
DoordashBusinessListResponse
> = {
id: 'doordash_list_businesses',
name: 'DoorDash List Businesses',
description: 'Lists all businesses owned by the developer.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'list_businesses',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to list businesses' } }
}
return { success: true, output: { businesses: data.output.businesses ?? [] } }
},
outputs: {
businesses: {
type: 'array',
description: 'List of businesses',
items: {
type: 'object',
properties: {
externalBusinessId: { type: 'string', description: 'Business ID' },
name: { type: 'string', description: 'Business name' },
description: { type: 'string', description: 'Business description' },
activationStatus: { type: 'string', description: 'Activation status' },
},
},
},
},
}

View File

@@ -0,0 +1,68 @@
import type { DoordashListStoresParams, DoordashStoreListResponse } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const listStoresTool: ToolConfig<DoordashListStoresParams, DoordashStoreListResponse> = {
id: 'doordash_list_stores',
name: 'DoorDash List Stores',
description: 'Lists all stores under a business.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Business ID to list stores for',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'list_stores',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to list stores' } }
}
return { success: true, output: { stores: data.output.stores ?? [] } }
},
outputs: {
stores: {
type: 'array',
description: 'List of stores',
items: {
type: 'object',
properties: {
externalStoreId: { type: 'string', description: 'Store ID' },
name: { type: 'string', description: 'Store name' },
phoneNumber: { type: 'string', description: 'Store phone number' },
address: { type: 'string', description: 'Store address' },
},
},
},
},
}

View File

@@ -0,0 +1,238 @@
import type { OutputProperty, ToolResponse } from '@/tools/types'
export interface DoordashBaseParams {
developerId: string
keyId: string
signingSecret: string
}
export interface DoordashCreateQuoteParams extends DoordashBaseParams {
externalDeliveryId: string
pickupAddress: string
pickupPhoneNumber: string
pickupBusinessName: string
dropoffAddress: string
dropoffPhoneNumber: string
dropoffBusinessName: string
orderValue: string
pickupInstructions?: string
dropoffInstructions?: string
tip?: string
dropoffContactSendNotifications?: string
actionIfUndeliverable?: string
contactlessDropoff?: string
dropoffRequiresSignature?: string
dropoffContactGivenName?: string
dropoffContactFamilyName?: string
pickupTime?: string
dropoffTime?: string
}
export interface DoordashAcceptQuoteParams extends DoordashBaseParams {
externalDeliveryId: string
tip?: string
dropoffPhoneNumber?: string
}
export interface DoordashCreateDeliveryParams extends DoordashBaseParams {
externalDeliveryId: string
pickupAddress: string
pickupPhoneNumber: string
pickupBusinessName: string
dropoffAddress: string
dropoffPhoneNumber: string
dropoffBusinessName: string
orderValue: string
pickupInstructions?: string
dropoffInstructions?: string
tip?: string
dropoffContactSendNotifications?: string
actionIfUndeliverable?: string
contactlessDropoff?: string
dropoffRequiresSignature?: string
dropoffContactGivenName?: string
dropoffContactFamilyName?: string
pickupTime?: string
dropoffTime?: string
}
export interface DoordashGetDeliveryParams extends DoordashBaseParams {
externalDeliveryId: string
}
export interface DoordashUpdateDeliveryParams extends DoordashBaseParams {
externalDeliveryId: string
tip?: string
dropoffPhoneNumber?: string
dropoffInstructions?: string
}
export interface DoordashCancelDeliveryParams extends DoordashBaseParams {
externalDeliveryId: string
}
export interface DoordashQuoteResponse extends ToolResponse {
output: {
externalDeliveryId: string
deliveryStatus: string
fee: number | null
currency: string | null
pickupTimeEstimated: string | null
dropoffTimeEstimated: string | null
}
}
export interface DoordashDeliveryResponse extends ToolResponse {
output: {
externalDeliveryId: string
deliveryStatus: string
fee: number | null
tip: number | null
orderValue: number | null
currency: string | null
trackingUrl: string | null
supportReference: string | null
dasherName: string | null
dasherId: number | null
contactlessDropoff: boolean | null
dropoffVerificationImageUrl: string | null
cancellationReason: string | null
pickupTimeEstimated: string | null
pickupTimeActual: string | null
dropoffTimeEstimated: string | null
dropoffTimeActual: string | null
pickupAddress: string | null
dropoffAddress: string | null
updatedAt: string | null
}
}
export interface DoordashCancelResponse extends ToolResponse {
output: {
externalDeliveryId: string
deliveryStatus: string
}
}
export const QUOTE_OUTPUT_PROPERTIES = {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status (e.g., quote)' },
fee: { type: 'number', description: 'Delivery fee in cents' },
currency: { type: 'string', description: 'Fee currency code (e.g., USD)' },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time (ISO 8601)' },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time (ISO 8601)' },
} as const satisfies Record<string, OutputProperty>
export const DELIVERY_OUTPUT_PROPERTIES = {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: {
type: 'string',
description:
'Delivery status (quote, created, scheduled, assigned, picked_up, delivered, cancelled, returned)',
},
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents', optional: true },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code (e.g., USD)' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name', optional: true },
dasherId: { type: 'number', description: 'Assigned Dasher ID', optional: true },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used', optional: true },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL at dropoff', optional: true },
cancellationReason: { type: 'string', description: 'Reason for cancellation', optional: true },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time (ISO 8601)' },
pickupTimeActual: {
type: 'string',
description: 'Actual pickup time (ISO 8601)',
optional: true,
},
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time (ISO 8601)' },
dropoffTimeActual: {
type: 'string',
description: 'Actual dropoff time (ISO 8601)',
optional: true,
},
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
} as const satisfies Record<string, OutputProperty>
export interface DoordashCreateBusinessParams extends DoordashBaseParams {
externalBusinessId: string
name: string
description?: string
}
export interface DoordashListBusinessesParams extends DoordashBaseParams {}
export interface DoordashUpdateBusinessParams extends DoordashBaseParams {
externalBusinessId: string
name?: string
description?: string
}
export interface DoordashCreateStoreParams extends DoordashBaseParams {
externalBusinessId: string
externalStoreId: string
name: string
phoneNumber: string
address: string
}
export interface DoordashListStoresParams extends DoordashBaseParams {
externalBusinessId: string
}
export interface DoordashGetStoreParams extends DoordashBaseParams {
externalBusinessId: string
externalStoreId: string
}
export interface DoordashUpdateStoreParams extends DoordashBaseParams {
externalBusinessId: string
externalStoreId: string
name?: string
phoneNumber?: string
address?: string
}
export interface DoordashBusinessResponse extends ToolResponse {
output: {
externalBusinessId: string
name: string
description: string | null
activationStatus: string | null
}
}
export interface DoordashBusinessListResponse extends ToolResponse {
output: {
businesses: Array<{
externalBusinessId: string
name: string
description: string | null
activationStatus: string | null
}>
}
}
export interface DoordashStoreResponse extends ToolResponse {
output: {
externalStoreId: string
name: string
phoneNumber: string | null
address: string | null
}
}
export interface DoordashStoreListResponse extends ToolResponse {
output: {
stores: Array<{
externalStoreId: string
name: string
phoneNumber: string | null
address: string | null
}>
}
}

View File

@@ -0,0 +1,81 @@
import type { DoordashBusinessResponse, DoordashUpdateBusinessParams } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const updateBusinessTool: ToolConfig<DoordashUpdateBusinessParams, DoordashBusinessResponse> = {
id: 'doordash_update_business',
name: 'DoorDash Update Business',
description: 'Updates a business entity name or description.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Business ID to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated business name',
},
description: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated business description',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'update_business',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
name: params.name,
description: params.description,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to update business' } }
}
return {
success: true,
output: {
externalBusinessId: data.output.externalBusinessId ?? '',
name: data.output.name ?? '',
description: data.output.description ?? null,
activationStatus: data.output.activationStatus ?? null,
},
}
},
outputs: {
externalBusinessId: { type: 'string', description: 'Business ID' },
name: { type: 'string', description: 'Business name' },
description: { type: 'string', description: 'Business description', optional: true },
activationStatus: { type: 'string', description: 'Activation status', optional: true },
},
}

View File

@@ -0,0 +1,133 @@
import type {
DoordashDeliveryResponse,
DoordashUpdateDeliveryParams,
} from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const updateDeliveryTool: ToolConfig<
DoordashUpdateDeliveryParams,
DoordashDeliveryResponse
> = {
id: 'doordash_update_delivery',
name: 'DoorDash Update Delivery',
description: 'Updates a delivery. Only tip and dropoff details can be modified after creation.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Key ID',
},
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalDeliveryId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'External delivery ID to update',
},
tip: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated tip amount in cents',
},
dropoffPhoneNumber: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated dropoff phone number',
},
dropoffInstructions: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated dropoff instructions',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'update_delivery',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalDeliveryId: params.externalDeliveryId,
tip: params.tip,
dropoffPhoneNumber: params.dropoffPhoneNumber,
dropoffInstructions: params.dropoffInstructions,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to update delivery' } }
}
return {
success: true,
output: {
externalDeliveryId: data.output.externalDeliveryId ?? '',
deliveryStatus: data.output.deliveryStatus ?? '',
fee: data.output.fee ?? null,
tip: data.output.tip ?? null,
orderValue: data.output.orderValue ?? null,
currency: data.output.currency ?? null,
trackingUrl: data.output.trackingUrl ?? null,
supportReference: data.output.supportReference ?? null,
dasherName: data.output.dasherName ?? null,
dasherId: data.output.dasherId ?? null,
contactlessDropoff: data.output.contactlessDropoff ?? null,
dropoffVerificationImageUrl: data.output.dropoffVerificationImageUrl ?? null,
cancellationReason: data.output.cancellationReason ?? null,
pickupTimeEstimated: data.output.pickupTimeEstimated ?? null,
pickupTimeActual: data.output.pickupTimeActual ?? null,
dropoffTimeEstimated: data.output.dropoffTimeEstimated ?? null,
dropoffTimeActual: data.output.dropoffTimeActual ?? null,
pickupAddress: data.output.pickupAddress ?? null,
dropoffAddress: data.output.dropoffAddress ?? null,
updatedAt: data.output.updatedAt ?? null,
},
}
},
outputs: {
externalDeliveryId: { type: 'string', description: 'External delivery ID' },
deliveryStatus: { type: 'string', description: 'Delivery status' },
fee: { type: 'number', description: 'Delivery fee in cents' },
tip: { type: 'number', description: 'Tip amount in cents', optional: true },
orderValue: { type: 'number', description: 'Order value in cents' },
currency: { type: 'string', description: 'Fee currency code' },
trackingUrl: { type: 'string', description: 'Delivery tracking URL' },
supportReference: { type: 'string', description: 'Support reference ID' },
dasherName: { type: 'string', description: 'Assigned Dasher name', optional: true },
dasherId: { type: 'number', description: 'Assigned Dasher ID', optional: true },
contactlessDropoff: { type: 'boolean', description: 'Whether contactless dropoff was used', optional: true },
dropoffVerificationImageUrl: { type: 'string', description: 'Photo verification URL at dropoff', optional: true },
cancellationReason: { type: 'string', description: 'Reason for cancellation', optional: true },
pickupTimeEstimated: { type: 'string', description: 'Estimated pickup time' },
pickupTimeActual: { type: 'string', description: 'Actual pickup time', optional: true },
dropoffTimeEstimated: { type: 'string', description: 'Estimated dropoff time' },
dropoffTimeActual: { type: 'string', description: 'Actual dropoff time', optional: true },
pickupAddress: { type: 'string', description: 'Pickup address' },
dropoffAddress: { type: 'string', description: 'Dropoff address' },
updatedAt: { type: 'string', description: 'Last updated timestamp', optional: true },
},
}

View File

@@ -0,0 +1,95 @@
import type { DoordashStoreResponse, DoordashUpdateStoreParams } from '@/tools/doordash/types'
import type { ToolConfig } from '@/tools/types'
export const updateStoreTool: ToolConfig<DoordashUpdateStoreParams, DoordashStoreResponse> = {
id: 'doordash_update_store',
name: 'DoorDash Update Store',
description: 'Updates a store location name, phone number, or address.',
version: '1.0.0',
params: {
developerId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Developer ID',
},
keyId: { type: 'string', required: true, visibility: 'user-only', description: 'DoorDash Key ID' },
signingSecret: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'DoorDash Signing Secret',
},
externalBusinessId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Parent business ID',
},
externalStoreId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Store ID to update',
},
name: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated store name',
},
phoneNumber: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated phone number',
},
address: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Updated address',
},
},
request: {
url: '/api/tools/doordash',
method: 'POST',
headers: () => ({ 'Content-Type': 'application/json' }),
body: (params) => ({
operation: 'update_store',
developerId: params.developerId,
keyId: params.keyId,
signingSecret: params.signingSecret,
externalBusinessId: params.externalBusinessId,
externalStoreId: params.externalStoreId,
name: params.name,
phoneNumber: params.phoneNumber,
address: params.address,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.success) {
return { success: false, output: { error: data.error ?? 'Failed to update store' } }
}
return {
success: true,
output: {
externalStoreId: data.output.externalStoreId ?? '',
name: data.output.name ?? '',
phoneNumber: data.output.phoneNumber ?? null,
address: data.output.address ?? null,
},
}
},
outputs: {
externalStoreId: { type: 'string', description: 'Store ID' },
name: { type: 'string', description: 'Store name' },
phoneNumber: { type: 'string', description: 'Store phone number' },
address: { type: 'string', description: 'Store address' },
},
}

View File

@@ -392,6 +392,21 @@ import {
docusignSendEnvelopeTool,
docusignVoidEnvelopeTool,
} from '@/tools/docusign'
import {
doordashAcceptQuoteTool,
doordashCancelDeliveryTool,
doordashCreateBusinessTool,
doordashCreateDeliveryTool,
doordashCreateQuoteTool,
doordashCreateStoreTool,
doordashGetDeliveryTool,
doordashGetStoreTool,
doordashListBusinessesTool,
doordashListStoresTool,
doordashUpdateBusinessTool,
doordashUpdateDeliveryTool,
doordashUpdateStoreTool,
} from '@/tools/doordash'
import {
dropboxCopyTool,
dropboxCreateFolderTool,
@@ -4050,6 +4065,19 @@ export const tools: Record<string, ToolConfig> = {
docusign_list_templates: docusignListTemplatesTool,
docusign_send_envelope: docusignSendEnvelopeTool,
docusign_void_envelope: docusignVoidEnvelopeTool,
doordash_accept_quote: doordashAcceptQuoteTool,
doordash_cancel_delivery: doordashCancelDeliveryTool,
doordash_create_business: doordashCreateBusinessTool,
doordash_create_delivery: doordashCreateDeliveryTool,
doordash_create_quote: doordashCreateQuoteTool,
doordash_create_store: doordashCreateStoreTool,
doordash_get_delivery: doordashGetDeliveryTool,
doordash_get_store: doordashGetStoreTool,
doordash_list_businesses: doordashListBusinessesTool,
doordash_list_stores: doordashListStoresTool,
doordash_update_business: doordashUpdateBusinessTool,
doordash_update_delivery: doordashUpdateDeliveryTool,
doordash_update_store: doordashUpdateStoreTool,
datadog_submit_metrics: datadogSubmitMetricsTool,
datadog_query_timeseries: datadogQueryTimeseriesTool,
datadog_create_event: datadogCreateEventTool,