Inviting & connecting
A supplier adds a customer from Customers by entering a contact's phone or email. If that phone or email already belongs to a restaurant on Clipp, the supplier picks the location and sends a connection request, which the restaurant has to approve. If it doesn't, the supplier creates a new customer: the restaurant is set up straight away, and an invitation goes to the contact to sign in. A newly connected customer carries a Recently Connected badge for 30 days. Orders don't clear it early (see Known limitations).
Who uses it
- Supplier staff invite customers, resend invitations, and watch for newly connected customers.
- Restaurants accept the invitation or connection request in the restaurant app.
How it works
Step 1: the contact
The form ("New Customer Form") opens on Contact Information:
| Field | Rule |
|---|---|
| First Name | Required: "First Name is required" |
| Last Name (Optional) | |
| Primary Phone Number | Phone or email needed to send an invitation |
| Primary Email | "Invalid Email" if malformed |
As the phone or email is typed, the app looks for restaurants already on Clipp that match the phone or email, on the restaurant's business record or on any of its users. A match on a parent business also lists all its locations. Restaurants you're already connected to or have already invited are left out.
Step 2a: a match was found, so connect to it
"This email or phone number is linked to an existing restaurant account. Select one location to connect with and send a request for approval."
| Situation | What the form does |
|---|---|
| One or more locations to choose from | Pick one. The button reads Send Connection Request and sends straight away. The business step is skipped |
| Every match is already a customer or invited | "This restaurant is already in your customer list. Please revise the contact information to continue." The button is disabled |
| The contact is a Clipp user with no restaurant to connect to | "This contact belongs to an existing account with no available restaurants. Please revise the contact information to proceed." The button is disabled |
| The contact is a registered user and nothing is picked | "This contact is associated with a registered user. You must select a restaurant to connect with." |
After sending: "Connection request sent". "The restaurant will receive an email invitation to approve your connection."
- The restaurant shows in your list as an Invited Customer with a Pending Invitation. Tooltip: "The customer has yet to accept your invite on their mobile app. However, you may still place an order manually with them."
- Until it accepts, its details are read-only to you, you can't add contacts, and chat is disabled. Its address is hidden in your customers list.
- When it accepts, you're connected. The contact you typed becomes your primary contact.
Step 2b: no match, so create a new customer
The form continues to the business step: Business Information (Business Name, required), Customer Ref ID (optional), shipping and billing addresses, and "Upload tax document".
| Contact entered | Result |
|---|---|
| Phone and/or email | The restaurant is created with a login for the contact as owner, you're connected straight away, and an invitation is sent to sign in |
| No phone and no email | The restaurant is created without a login and without an invitation. Only the name (if typed) is kept as your contact |
After creating: "Customer Created". "An invitation has been sent to the restaurant. Their profile has been created with a Pending status. Once they sign up, the status will be updated and you'll be fully connected."
A new customer whose phone or email matches an existing restaurant can't be created. The server refuses: "Cannot create a new customer — the provided contact matches one or more existing restaurants. Choose a match or revise the contact information."
Duplicate details
| Field | Message |
|---|---|
| Phone | "Phone number is already being used by another account. Please try a different one or reach out to support." |
| "An account with that email already exists…" | |
| EIN | "EIN/Tax ID is already being used by another account…" |
Resend Invitation
On the customer's page, Resend Invitation is shown until the customer is connected.
| Rule | Detail |
|---|---|
| Disabled when | There's no email or phone to send to. Tooltip: "Email address or phone number required to resend the invitation" |
| Sends by | Email if the invitation has a valid email, otherwise text. Never both |
| Sends to | The restaurant owner's email (or phone), falling back to the invitation's, then the business's |
| Messages | "Invitation has been resent successfully" / "Failed to resend invitation" |
| After the restaurant has accepted | The button is hidden. The server would refuse: "Invitation is already accepted" |
Changing the primary contact's phone or email before the restaurant accepts re-sends the invitation automatically to the new details. See Contacts.
Accepting
When the restaurant accepts:
| Before | After | |
|---|---|---|
| Customers list | Invited Customer, Pending Invitation | Connected Customer, with Recently Connected |
| Your primary contact | (the invitation's contact) | The contact you invited, saved as your primary contact |
| Business details | Read-only (existing restaurant) | Editable |
| Orders you placed for them before | Visible to you only (verify) | Visible to the restaurant too |
| Email to the restaurant | "Connected to supplier" email | |
| The restaurant's own name, address, EIN | Unchanged | Unchanged |
Recently Connected
A customer shows Recently Connected for the first 30 days after you connected. It clears earlier only when an order the restaurant placed from its app in the earlier order records moves past Pending. Orders placed through current orders never clear it (see Known limitations).
Tooltip: "This customer was recently connected via the app. Please verify their information matches your Primary Business Information. Edit in Customer Details if needed."
| Day | Event | Badge |
|---|---|---|
| Oct 1 | Restaurant accepts | Recently Connected |
| Oct 3 | Restaurant places an order | Still shown |
| Oct 4 | You confirm it | Still shown (current orders don't clear it) |
| Oct 31 | 30 days after Oct 1 | Gone |
Restaurant onboarding
When a restaurant signs up in the restaurant app it enters its own shipping address and, unless it ticks "same as shipping", a billing address. Those become the restaurant's business details, which you see as soon as you're connected. This flow lives in the restaurant mobile app, not in this repository (verify the address rules and whether the restaurant can edit them afterwards).
Where it shows up
Customers list (Connected Customer, Invited Customer, Pending Invitation, Recently Connected, Inactive Customers) · Customer detail (Resend Invitation) · Invite form · Invitation email and text · Restaurant app.
Permissions
| Action | Who |
|---|---|
| Invite a customer, resend an invitation | Supplier staff with access to Customers (verify: the server applies no role check) |
| Accept | The invited restaurant contact |
Decisions
- A contact that matches an existing restaurant must connect to it. No duplicate restaurants for the same phone or email. (PRD: Dual Data)
- An existing restaurant approves the connection; a new one is created at once. You can't take over a restaurant that already exists.
- Recently Connected is a 30-day nudge to check details, not a status.
- Invitations are scoped to the inviting supplier. (#2463)
Known limitations
- Confirming a current order doesn't clear Recently Connected. The early-clearing check reads only app orders in the earlier order records, so a badge whose restaurant ordered through current orders stays the full 30 days. The DDNC-002 spec describes the intended behaviour.
- Resend can report success without sending. If the restaurant's owner has an email but no phone and the invitation is sent by text, nothing goes out but the app says "Invitation has been resent successfully" (verify).
- Resend only reaches the owner, not the contact you typed, once the restaurant has an owner.
- Inviting and resending have no server-side permission check (security review needed, noted in #2463).
- A Customer Ref ID typed while connecting to an existing restaurant is lost.
- The customers list hides an invited restaurant's address but shows its name, phone and email.
- The "removed team member" rules in the spec (orphaned clerks) aren't built.
FAQ
Why can't I create this customer? It says the contact matches an existing restaurant. That phone or email is already on Clipp. Pick the matching location and send a connection request, or use a different contact.
I sent a connection request. Why can't I edit their details? The restaurant already had an account, so its details stay its own until it accepts.
Can I place orders before they accept? Yes. "You may still place an order manually with them."
Why did the "Recently Connected" badge disappear? 30 days passed since they connected, or an app order the restaurant placed in the earlier order records was confirmed.
The resend went by text, not email. Why? Resend uses email when the invitation has a valid email, otherwise a text. It never sends both.
Specs
- DDIR-006: a matched parent always lists its locations; there's no "family members connected" rule.
- DDIR-009: selecting a match doesn't keep any of your typed business details. They belong to the restaurant.
- DDIR-011: a user with no business is blocked in the form ("…no available restaurants").
- DDIR-012: the message differs ("This contact is associated with a registered user. You must select a restaurant to connect with.").
- DDIR-019 – DDIR-023 (orphaned clerks): not built.
- DDRI-001, DDRI-002: hold only when the restaurant has no owner yet. Otherwise resend goes to the owner.
- DDNC: the badge is "Recently Connected", not "Newly Connected", and it also expires after 30 days.
- DDRO: the restaurant app's onboarding isn't in this repository; the "can't edit addresses after onboarding" rule isn't enforced by the server.
# prefix: DDIR
Feature: Inviting a restaurant
A supplier can invite a restaurant through the Clipp app.
The system checks if the provided email or phone matches existing
businesses or users. Based on the results, the supplier either
creates a new restaurant or connects to an existing one.
Background:
Given supplier "Miguel Supplier Test" is inviting a restaurant with the following information:
| First Name | Johnny |
| Last Name | Smith |
| Primary Phone | +19179171917 |
| Primary Email | eder.chamale+john.pizza.iii@gmail.com |
| Business Name | John Pizza III |
| Business Tax Id | 45456644 |
| Business Shipping Full Address | 123 Wall st |
| Business Shipping City | Brooklyn |
| Business Shipping State | NY |
| Business Shipping Zip | 11222 |
| Business Billing Full Address | 123 Wall st |
| Business Billing City | Brooklyn |
| Business Billing State | NY |
| Business Billing Zip | 11222 |
And the system performs a unified lookup across business and user collections
Rule: No user information provided — business is created without invitation
Scenario: DDIR-001 Supplier creates a business without contact information
Given the supplier does not provide any user information (name, email, or phone)
When the supplier submits the business information
Then a new restaurant is created with only the business information
And no invitation is sent
And no owner is assigned to the restaurant
And the system does not perform a unified lookup
Rule: No matches found — a new restaurant is created
Scenario: DDIR-002 New business and new contact person
Given no business or user matches the provided email or phone
When the supplier submits the invitation
Then a new restaurant is created with the provided information
And the invited user becomes the owner of the restaurant
And an invitation is sent to the provided email
Rule: All matched locations are already connected or invited
Scenario: DDIR-003 Supplier attempts to invite
Given all businesses matching the provided email or phone are already connected to or invited by the supplier
Then the supplier is notified that the business already exists
And the supplier cannot proceed with the invitation
Rule: Matched businesses are shown, excluding already connected or invited ones
Scenario Outline: DDIR-004 Match by <field> in business collection
Given a restaurant with the <field> "<value>" exists
And the restaurant is not already connected to or invited by the supplier
Then the restaurant appears in the match results
Examples:
| field | value |
| email | eder.chamale+john.pizza.iii@gmail.com |
| phone number | +19179171917 |
Scenario Outline: DDIR-005 Match by <field> in user collection
Given a user with the <field> "<value>" exists
And the user is the owner of "John Pizza Original"
Then "John Pizza Original" appears in the match results
Examples:
| field | value |
| email | eder.chamale+john.pizza.iii@gmail.com |
| phone number | +19179171917 |
Rule: Only directly matched businesses are shown; connected family members expand visibility
Scenario: DDIR-006 No family members are connected
Given "John Pizza Parent" matches the provided email
And "John Pizza Parent" has children "John Pizza Child A" and "John Pizza Child B"
And none of the family businesses are connected to the supplier
Then only "John Pizza Parent" appears in the match results
Scenario: DDIR-007 Parent is already connected
Given "John Pizza Parent" is already connected to the supplier
And "John Pizza Child A" matches the provided email
Then "John Pizza Child A" appears in the match results
Scenario: DDIR-008 Child is already connected
Given "John Pizza Child A" is already connected to the supplier
And "John Pizza Parent" matches the provided email
Then "John Pizza Parent" and "John Pizza Child B" appear in the match results
Rule: Selecting a match connects the supplier to the existing restaurant
Scenario: DDIR-009 Supplier selects "John Pizza Original"
When the supplier selects "John Pizza Original" and submits the invitation
Then a supplier customer record is created with the supplier's original input data
And the customer record is linked to the existing "John Pizza Original"
And an invitation is sent to "John Pizza Original"
And "John Pizza Original" retains its own independent data
Rule: A new contact person can skip matches and create a new restaurant
Scenario: DDIR-010 Supplier does not select any match
Given no user with the provided email or phone exists
When the supplier submits the invitation without selecting a match
Then a new restaurant is created with the provided information
Scenario: DDIR-011 User exists but is not a member of any business
Given a user with the provided email exists but is not a member of any business
When the supplier submits the invitation without selecting a match
Then a new restaurant is created with the provided information
And the existing user becomes the owner of the restaurant
And an invitation is sent to the provided email
Rule: An existing contact person must connect to one of the matched businesses
Scenario: DDIR-012 Supplier does not select any match
Given a user with the provided email exists in another business hierarchy
When the supplier submits the invitation without selecting a match
Then the supplier receives an error
And the supplier is informed that the contact person is already a member of another business
Rule: The owner retains ownership across parent and child businesses
Scenario: DDIR-013 Owner creates child businesses after onboarding
Given the owner of "John Pizza III" has completed onboarding
When the owner creates child businesses "John Pizza Express" and "John Pizza Catering"
Then the owner remains the owner of "John Pizza III"
And the owner is the owner of "John Pizza Express" and "John Pizza Catering"
Rule: The owner can invite users with specific roles to parent and child businesses
Scenario: DDIR-014 Owner invites a clerk to the parent business
Given the owner of "John Pizza III" has completed onboarding
When the owner invites a user as a clerk to "John Pizza III"
Then the invited user has the clerk role on "John Pizza III"
And the owner remains the owner of "John Pizza III"
Scenario: DDIR-015 Owner invites a manager to a child business
Given the owner of "John Pizza III" has a child business "John Pizza Express"
When the owner invites a user as a manager to "John Pizza Express"
Then the invited user has the manager role on "John Pizza Express"
And the owner remains the owner of "John Pizza Express"
Rule: A supplier invitation to a non-owner does not change ownership
Scenario Outline: DDIR-016 Supplier invites a clerk from a parent restaurant using <field>
Given "John Pizza III" has completed onboarding and is connected to another supplier
And "John Pizza III" has a clerk with the restaurant info permission
When a supplier invites "John Pizza III" using the clerk's <field>
And the clerk accepts the invitation
Then the clerk does not become the owner of "John Pizza III"
And the original owner remains the owner of "John Pizza III"
Examples:
| field |
| email |
| phone number |
Scenario Outline: DDIR-017 Supplier invites a clerk from a child location using <field>
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza III" is connected to the supplier
And "John Pizza Express" has a clerk with the restaurant info permission
When the supplier invites "John Pizza Express" using the clerk's <field>
And the clerk accepts the invitation
Then the clerk does not become the owner of "John Pizza Express"
And the original owner remains the owner of "John Pizza Express"
Examples:
| field |
| email |
| phone number |
Scenario Outline: DDIR-018 Supplier invites a manager from a child business using <field>
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza Express" has a manager with the restaurant info permission
When a supplier invites "John Pizza Express" using the manager's <field>
And the manager accepts the invitation
Then the manager does not become the owner of "John Pizza Express"
And the original owner remains the owner of "John Pizza Express"
Examples:
| field |
| email |
| phone number |
Rule: Removing a team member auto-revokes pending supplier invitations to child locations
Scenario: DDIR-019 Clerk removed while invitation is pending for a child location
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza III" is connected to the supplier
And "John Pizza Express" has a clerk with the restaurant info permission
And the supplier has sent an invitation to "John Pizza Express" using the clerk's email
When the owner removes the clerk from "John Pizza Express"
Then the pending invitation for "John Pizza Express" is automatically revoked
And the supplier is notified that the invitation was revoked because the contact is no longer a team member
Scenario: DDIR-020 Clerk removed while invitation is pending for a parent business
Given "John Pizza III" has completed onboarding and is connected to another supplier
And "John Pizza III" has a clerk with the restaurant info permission
And a supplier has sent an invitation to "John Pizza III" using the clerk's email
When the owner removes the clerk from "John Pizza III"
Then the pending invitation for "John Pizza III" is automatically revoked
And the supplier is notified that the invitation was revoked because the contact is no longer a team member
Rule: A supplier cannot invite a child location using an orphaned clerk's contact info
Scenario Outline: DDIR-021 Supplier invites a child location using an orphaned clerk's <field>
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza III" is connected to the supplier
And "John Pizza Express" previously had a clerk who has been removed from the team
When the supplier invites "John Pizza Express" using the former clerk's <field>
Then the supplier receives an error
And the supplier is informed that the contact is no longer a team member of "John Pizza Express"
Examples:
| field |
| email |
| phone number |
Rule: Resending an invitation to a child location is blocked when the contact has been orphaned
Scenario: DDIR-022 Supplier tries to resend an invitation after the clerk was removed
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza III" is connected to the supplier
And the supplier previously invited "John Pizza Express" using a clerk's email
And the clerk has since been removed from "John Pizza Express"
When the supplier attempts to resend the invitation
Then the system rejects the resend request
And the supplier is informed that the contact is no longer a team member of "John Pizza Express"
Rule: An orphaned clerk cannot accept a pending invitation for a child location
Scenario: DDIR-023 Orphaned clerk tries to accept a pending invitation
Given "John Pizza Express" is a child of "John Pizza III"
And "John Pizza III" is connected to the supplier
And the supplier sent an invitation to "John Pizza Express" using a clerk's email
And the clerk has since been removed from "John Pizza Express"
When the former clerk attempts to accept the invitation
Then the system rejects the acceptance
And the former clerk is informed they are no longer a team member of "John Pizza Express"
# prefix: DDRI
Feature: Resend invitation
A supplier can resend an invitation to a restaurant that has not yet
connected. The invitation is always sent to the current primary contact
information on file, not to outdated contact info.
Background:
Given supplier "Miguel Supplier Test" has invited "John Pizza III" with:
| Primary Email | eder.chamale+john.pizza.iii@gmail.com |
| Primary Phone | +19179171917 |
And "John Pizza III" has not yet accepted the invitation
Rule: Resend invitation sends to the current primary contact
Scenario Outline: DDRI-001 Supplier resends invitation to current primary <channel>
Given the customer record for "John Pizza III" has primary <channel> "<current_value>"
When "Miguel Supplier Test" resends the invitation for "John Pizza III"
Then an invitation is sent to "<current_value>" via <channel>
Examples:
| channel | current_value |
| email | eder.chamale+john.pizza.iii@gmail.com |
| phone | +19179171917 |
Rule: Updated primary contact receives the resent invitation, not the outdated one
Scenario Outline: DDRI-002 Supplier updates primary <channel> before resending
Given "Miguel Supplier Test" updates the primary <channel> for "John Pizza III" to "<new_value>"
When "Miguel Supplier Test" resends the invitation for "John Pizza III"
Then an invitation is sent to "<new_value>" via <channel>
And no invitation is sent to "<old_value>" via <channel>
Examples:
| channel | new_value | old_value |
| email | eder.chamale+johnny.new@gmail.com | eder.chamale+john.pizza.iii@gmail.com |
| phone | +12125559999 | +19179171917 |
Scenario: DDRI-003 Multiple primary updates before resend sends only to the latest
Given "Miguel Supplier Test" updates the primary email for "John Pizza III" to "eder.chamale+johnny.v2@gmail.com"
And "Miguel Supplier Test" updates the primary email for "John Pizza III" to "eder.chamale+johnny.v3@gmail.com"
When "Miguel Supplier Test" resends the invitation for "John Pizza III"
Then an invitation is sent to "eder.chamale+johnny.v3@gmail.com" via email
And no invitation is sent to "eder.chamale+john.pizza.iii@gmail.com" via email
And no invitation is sent to "eder.chamale+johnny.v2@gmail.com" via email
Rule: Resend is not allowed after restaurant is connected
Scenario: DDRI-004 Supplier cannot resend invitation to a connected restaurant
Given "John Pizza III" has accepted the invitation and is connected to "Miguel Supplier Test"
When "Miguel Supplier Test" attempts to resend the invitation for "John Pizza III"
Then the system rejects the request
And the supplier is informed that the restaurant is already connected
# prefix: DDNC
Feature: Newly connected customer indicator
When a supplier connects to an existing restaurant or creates a new one,
the customer is marked as "Newly Connected" in the customers list until
the first order between them is confirmed.
Background:
Given supplier "Miguel Supplier Test" has a newly connected restaurant "John Pizza III"
Rule: A newly connected customer displays a "Newly Connected" indicator
Scenario: DDNC-001 Customer appears with "Newly Connected" indicator after connection
Given no orders have been confirmed between them
When the supplier views the customers list
Then "John Pizza III" displays a "Newly Connected" indicator
Scenario: DDNC-002 "Newly Connected" indicator is removed after the first confirmed order
When the first order between them is confirmed
Then "John Pizza III" no longer displays the "Newly Connected" indicator
Scenario: DDNC-003 "Newly Connected" indicator persists until an order is confirmed
Given orders exist between them but none are confirmed
When the supplier views the customers list
Then "John Pizza III" still displays the "Newly Connected" indicator
# prefix: DDRO
Feature: Restaurant onboarding — shipping and billing addresses
When a restaurant completes onboarding, it must provide a valid shipping address.
Billing defaults to the same as shipping but can be overridden.
These addresses become part of the restaurant's Business Identity and are
visible to connected suppliers. After onboarding, the restaurant cannot
edit shipping or billing addresses without contacting Clipp.
Background:
Given supplier "Miguel Supplier Test" has invited "John Pizza III"
And "John Pizza III" is completing the onboarding flow
Rule: Onboarding requires a valid shipping address
Scenario: DDRO-001 Restaurant provides a complete shipping address
Given the restaurant enters the following shipping address:
| Street | 123 Wall st |
| City | Brooklyn |
| State | NY |
| Zip | 11222 |
When the restaurant submits the onboarding form
Then the onboarding completes successfully
And the shipping address is saved to the restaurant's Business Identity
Scenario: DDRO-002 Restaurant submits onboarding without a shipping address
Given the restaurant has not entered a shipping address
When the restaurant attempts to submit the onboarding form
Then the onboarding is blocked with a validation error
And the restaurant is prompted to enter a valid shipping address
Scenario Outline: DDRO-003 Restaurant submits onboarding with an incomplete shipping address
Given the restaurant has not entered a <field>
When the restaurant attempts to submit the onboarding form
Then the onboarding is blocked with a validation error for <field>
Examples:
| field |
| Street |
| City |
| State |
| Zip |
Rule: Billing defaults to same as shipping address
Scenario: DDRO-004 Billing defaults to same as shipping
Given the restaurant has entered a valid shipping address
Then the billing address defaults to the same as the shipping address
Scenario: DDRO-005 Billing is auto-copied from shipping when not overridden
Given the restaurant enters the following shipping address:
| Street | 123 Wall st |
| City | Brooklyn |
| State | NY |
| Zip | 11222 |
And the restaurant does not provide a separate billing address
When the restaurant submits the onboarding form
Then the billing address is saved as:
| Street | 123 Wall st |
| City | Brooklyn |
| State | NY |
| Zip | 11222 |
Rule: Restaurant can provide a separate billing address
Scenario: DDRO-006 Restaurant provides a separate billing address
Given the restaurant enters a valid shipping address
And the restaurant provides a separate billing address:
| Street | 456 Broadway st |
| City | Manhattan |
| State | NY |
| Zip | 10001 |
When the restaurant submits the onboarding form
Then the onboarding completes successfully
And the billing address is saved separately from the shipping address
Scenario: DDRO-007 Restaurant opts for separate billing but does not provide one
Given the restaurant enters a valid shipping address
And the restaurant opts to provide a separate billing address
But the restaurant has not entered a billing address
When the restaurant attempts to submit the onboarding form
Then the onboarding is blocked with a validation error
And the restaurant is prompted to enter a valid billing address
Rule: Supplier can see the restaurant's addresses after connection
Scenario: DDRO-008 Supplier views connected restaurant's addresses
Given "John Pizza III" has completed onboarding with:
| Shipping Street | 123 Wall st |
| Shipping City | Brooklyn |
| Shipping State | NY |
| Shipping Zip | 11222 |
| Billing Street | 123 Wall st |
| Billing City | Brooklyn |
| Billing State | NY |
| Billing Zip | 11222 |
And "John Pizza III" is connected to "Miguel Supplier Test"
When "Miguel Supplier Test" views the customer record for "John Pizza III"
Then the supplier can see the restaurant's shipping address
And the supplier can see the restaurant's billing address
Rule: Restaurant cannot edit shipping or billing after onboarding
Scenario Outline: DDRO-009 Restaurant attempts to edit <address_type> address after onboarding
Given "John Pizza III" has completed onboarding
When "John Pizza III" attempts to edit the <address_type> address
Then the system does not allow the change
And the restaurant is informed to contact Clipp to update their <address_type> address
Examples:
| address_type |
| shipping |
| billing |