VAPI + PostgreSQL: bookings confirmed on every call
When your phone rings during service, it’s easy to miss details. A name spelled wrong, the time misunderstood, or a “sure, we can do 7:30” that turns into an accidental double booking.
This VAPI booking automation hits restaurant owners hardest, but front-of-house managers and small teams running on a thin staff feel it too. You will confirm reservations on every call, even when nobody can pick up.
This guide walks you through what the workflow does, what you need, and how the pieces fit together in n8n so you can run bookings like a well-oiled system.
How This Automation Works
Here’s the complete workflow you’ll be setting up:
n8n Workflow Template: VAPI + PostgreSQL: bookings confirmed on every call
flowchart LR
subgraph sg0["Flow 1"]
direction LR
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Upsert Booking in Postgres "]
n4["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Respond: Booking Confirmatio.."]
n5["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Trigger: Booking Request (VA.."]
n3 --> n4
n5 --> n3
end
subgraph sg1["Flow 2"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Query Table Availability (Po.."]
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Respond: Availability Status.."]
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Trigger: Booking Request (VA.."]
n2 --> n0
n0 --> n1
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n3,n0 database
class n4,n5,n1,n2 api
classDef customIcon fill:none,stroke:none
class n3,n4,n5,n0,n1,n2 customIcon
Why This Matters: Missed calls and messy reservation logs
Restaurants don’t lose bookings because the food is bad. They lose bookings because the process is chaotic. The phone rings while you’re seating a table, running drinks, fixing a delivery issue, and someone shouts “Did we confirm the 8-top?” You scribble notes on paper, then later someone retypes them (sometimes). If two people take calls, you get two versions of the truth. Then the awkward part: calling a guest back to say you can’t honor the time you already agreed to.
It adds up fast. Here’s where it usually breaks down.
- Calls go to voicemail during rush hours, which means reservations quietly disappear.
- Availability checks happen “in someone’s head,” so double bookings sneak in on busy nights.
- Handwritten notes get re-entered later, and the errors show up at the worst possible time.
- There’s no clean record of what was promised, so staff spend time arguing with the calendar instead of serving guests.
What You’ll Build: A virtual receptionist that checks availability and confirms bookings
This workflow turns VAPI into a reliable, always-on receptionist. A caller shares the basics (name, requested time, party size). n8n receives that booking request via a webhook, then checks your PostgreSQL database to see if there’s capacity at that time. If the table is available, n8n writes the reservation into Postgres and immediately sends a confirmation back to VAPI so the caller hears a clear “you’re booked.” If it’s not available, it returns an availability response so the caller can choose another time instead of guessing. The end result is simple: fewer missed calls, fewer double bookings, and cleaner reservation data your team can trust.
The workflow starts with an incoming booking webhook from VAPI. Then Postgres does the real work: one query to check availability, and another action to store the booking. Finally, n8n responds back to VAPI with a confirmation or an alternative based on what your database says.
What You’re Building
| What Gets Automated | What You’ll Achieve |
|---|---|
|
|
Expected Results
Say you get about 20 booking calls on a Friday. If each call takes maybe 5 minutes to answer, confirm availability, and write it down, that’s about 100 minutes of staff attention, and it happens right in the middle of service. With this workflow, the “check and record” part is automated. Staff only steps in for edge cases, while confirmations happen in seconds after the caller provides details. That’s roughly an hour and a half back on your busiest day, plus fewer mistakes to fix later.
Before You Start
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- VAPI for handling phone calls and collecting details
- PostgreSQL to store bookings and check availability
- VAPI API credentials (get them from your VAPI dashboard)
Skill level: Intermediate. You’ll paste credentials, import the workflow, and map a couple fields to your database columns.
Want someone to build this for you? Talk to an automation expert (free 15-minute consultation).
Step by Step
A caller triggers a VAPI webhook. VAPI collects the booking details you care about (usually name, party size, and time) and sends them into n8n as a structured payload.
n8n checks your real availability in PostgreSQL. The workflow uses a Postgres query (“Fetch Table Availability”) to look up whether that time slot can accommodate the party size based on the rules you store in your database.
It either replies with options or stores the reservation. If availability is tight, n8n returns an “availability reply” back to VAPI so the caller can pick another time. If it’s available, the second webhook path stores the booking record in Postgres.
The caller gets an immediate confirmation. n8n sends a final webhook response (“Send Booking Confirmation”) so VAPI can confirm the booking in the same call, without “we’ll call you back.”
You can easily modify the availability logic to support table types, seating areas, or special events based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Webhook Trigger
Set up the two incoming webhook endpoints that start each booking flow.
- Add and open Incoming Booking Webhook A.
- Set HTTP Method to
POST. - Set Path to
027f0f14-93f4-42ff-90a7-715f23316a86. - Set Response Mode to
responseNodeso Return Availability Reply can respond. - Add and open Incoming Booking Webhook B.
- Set HTTP Method to
POST. - Set Path to
2f7eff83-2e85-45ee-b544-7f889ca3ad07. - Set Response Mode to
responseNodeso Send Booking Confirmation can respond.
Step 2: Connect Postgres for Availability Lookups
Configure the database read step that returns table availability.
- Open Fetch Table Availability.
- Credential Required: Connect your postgres credentials.
- Set Operation to
select. - Set Schema to
public. - Set Table to
table_id.
table_id table contains an available field, as Return Availability Reply uses {{ $json.available }}.Step 3: Configure the Availability Response
Return a JSON response to the availability webhook request.
- Open Return Availability Reply.
- Set Respond With to
json. - Set Response Body to
={ "results": [ { "toolCallId": "{{ $('Incoming Booking Webhook A').item.json.body.message.toolCalls[0].id }}", "result": "{{ $json.available }}" } ] }.
This node is triggered after Fetch Table Availability as defined in the execution flow.
Step 4: Store Booking Records
Upsert the booking details into Postgres before sending a confirmation.
- Open Store Booking Record.
- Credential Required: Connect your postgres credentials.
- Set Operation to
upsert. - Set Schema to
public. - Set Table to
table_id.
Step 5: Configure the Booking Confirmation Response
Return a JSON confirmation after the booking is stored.
- Open Send Booking Confirmation.
- Set Respond With to
json. - Set Response Body to
={ "results": [ { "toolCallId": "{{ $('Incoming Booking Webhook B').item.json.body.message.toolCalls[0].id }}", "result": "{{ $json.status }}" } ] }.
According to the execution flow, Store Booking Record → Send Booking Confirmation.
Step 6: Test and Activate Your Workflow
Validate both webhook paths and then enable the workflow for production.
- Click Execute Workflow and send a POST request to Incoming Booking Webhook A with a sample payload.
- Confirm Fetch Table Availability returns data and Return Availability Reply responds with a JSON body containing
resultandtoolCallId. - Send a POST request to Incoming Booking Webhook B with booking data.
- Verify Store Booking Record upserts into Postgres and Send Booking Confirmation returns a JSON response with
{{ $json.status }}. - Toggle the workflow to Active once tests pass.
Troubleshooting Tips
- VAPI credentials can expire or need specific permissions. If things break, check your VAPI project settings and webhook destination configuration first.
- If you’re seeing “available” when it’s clearly not, the PostgreSQL query is usually filtering on the wrong time format. Check how your database stores time zones and how VAPI sends the requested booking time.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever, especially if you’re using the AI Agent to answer restaurant questions in a specific tone.
Quick Answers
About an hour if your Postgres table is ready.
No. You’ll connect VAPI and PostgreSQL, then map fields like time and party size.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in VAPI usage costs and any AI usage if you enable an OpenAI Chat Model for Q&A.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and you should. Most customizations happen in the “Fetch Table Availability” Postgres query and the “Store Booking Record” insert, because that’s where your business rules live. Common tweaks include adding special requests (high chair, patio), blocking off event nights, and changing what counts as “available” based on party size. You can also adjust the VAPI input fields so callers confirm things like allergies or a callback number.
Usually it’s the webhook URL or an expired credential in VAPI. Confirm VAPI is pointing to the correct n8n production webhook, then re-save the VAPI API credentials in n8n. If the webhook is firing but your fields are blank, it’s often a mismatch in the JSON keys VAPI sends versus what your n8n mapping expects. Also check rate limiting if you’re load-testing with lots of calls in a short window.
On n8n Cloud Starter, you can typically handle thousands of webhook executions per month, and higher tiers scale from there. If you self-host, there’s no execution cap (it depends on your server). Practically, Postgres and your availability query are the main bottlenecks, not n8n. For most restaurants, the workflow feels instant because each call only runs a couple of database operations.
Often, yes, because database-first logic is where Zapier and Make can get clunky (and expensive) once you add branching. n8n handles Postgres queries cleanly, which is the heart of preventing double bookings. You also get the option to self-host, which matters if calls spike during events or holidays. If you only need “log a call somewhere,” Zapier is fine. If you need “check capacity, then write, then confirm,” n8n is a better fit. Talk to an automation expert if you want help choosing.
Once this is running, confirmations stop being a scramble. The workflow handles the repetitive parts so your team can focus on hospitality.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.