Skip to content

Integration  ·  Platform engineering

How to let customers connect their own accounts

A customer's connection expires on a Saturday and their sync stops without a word, and they find out from a report on Monday. How customers connect their accounts inside your product, the prompts that build it, and how to catch a broken connection before the customer does.

Built with Tray Headless

  1. System Your product
  2. Step Sign in, under your brand
  3. Step Check what was granted
  4. Step Watch every connection
  5. System Salesforce
Also Email the customer

The customer connects their account in your product, under your brand. A check on every connection warns them before it stops working.

The short answer

How do customers connect their own accounts to an embedded integration?

Letting customers connect their own accounts comes down to four things: a sign-in that happens inside your product and carries your name rather than an integration vendor's, a check straight after sign-in that the access granted is the access the integration needs, credentials held against that customer and never visible to your team, and a watch on every connection so an expired or revoked one is found and the customer told before their sync stops. With Tray Embedded the sign-in is the auth-only dialog or the config wizard, and a custom OAuth app plus your own domain keeps Tray's name off every screen. Most teams skip the watch. A connection that fails silently is found by the customer, a week late.

Stage 3 of 7: Customers connect their accounts. Part of Embedded integration, end to end : every stage, the systems it runs on and the guide that builds it.

What matters here

  • Sign-in should carry your name. A customer asked to authorise an app they've never heard of will hesitate, and some will stop.
  • Check the access granted, not just that sign-in finished. A customer who unticks a permission gets a sync that half works.
  • Your team should never see a customer's credentials. They are held against the customer, and used only for their instance.
  • Watch every connection. An expired token sends no error until the next run fails.
  • Tell the customer in your product, with one button to reconnect. A support ticket is the slow way to fix a sign-in.

Who this is for

You build the integration experience inside a software product. Customers connect their CRM or other apps to your product, and broken connections reach you as support tickets.

How it works in practice

From the customer clicking connect to their connection still working six months later.

  1. 1

    The customer clicks connect in your product

    Your page, your button. The sign-in opens in a popup under your own domain.

  2. 2

    They sign in to their app and approve access

    The approval screen names your product, because the sign-in uses your own app registration.

  3. 3

    The access granted is checked

    Against the permissions the integration needs, with a clear message if one was left out.

  4. 4

    The connection is stored against that customer

    Usable only by their instance, never shown to your team or to other customers.

  5. 5

    Every connection is checked on a schedule

    So an expired, revoked or downgraded connection is found before a sync depends on it.

  6. 6

    The customer is told, with one way to fix it

    In your product and by email, with a reconnect button that opens the same sign-in.

What account connection is made of

Four parts. The last one is what keeps support out of the loop.

A sign-in under your brand

Your own OAuth app registration for each service, and your own domain on the sign-in popup, so no screen shows another vendor's name.

A permissions check

Straight after sign-in, a call that proves the access works for what the integration does, not just that a token came back.

Credentials held for the customer

Stored against the customer's own user, reused if they connect a second integration to the same account, and never readable by your staff.

A connection watch

A scheduled check of every customer's connections, with warnings before a sync fails and a reconnect link in the warning.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    Register your own app with each service

    So the approval screen names your product.

    For each service the integration connects to, starting with
    Salesforce, register an OAuth app under our company's developer
    account. Use our product name, logo and support address.
    
    Add both redirect addresses: Tray's default one, and the one on our
    own subdomain (ours.integration-authentication.com, or the EU
    equivalent). Then attach the app to the authentication in Tray
    Embedded so customers sign in through it.
    
    Ask only for the permissions the integration uses. A long list of
    scopes on the approval screen is a reason for a customer's admin to
    say no.
  2. 2

    Put the sign-in in your product

    Your page, your button, your domain.

    Headless skills build-workflow

    Use build-workflow for the backend calls. When a customer signs in to
    our product for the first time, create their Tray end user with our
    own customer id as the external id, so the two records always match.
    
    On our integrations page, open the sign-in with the auth-only dialog
    when the integration needs only a connection, and with the config
    wizard when it also needs settings. Both open on our own subdomain.
    
    If the customer already has a connection to the same account from
    another integration, offer it rather than asking them to sign in
    again.
  3. 3

    Check what was actually granted

    A sync that half works is worse than one that refuses.

    Headless skills build-workflow tray-gotchas

    Use build-workflow and tray-gotchas. Straight after the customer signs
    in, run one harmless read for each kind of record the integration
    uses: list one account, one contact, one opportunity.
    
    If any read is refused, tell the customer which permission is missing
    and offer to sign in again. Don't create the instance until every read
    passes.
    
    Record which user they signed in as. A connection made by a user who
    later leaves the customer's company is the most common reason a sync
    stops.
  4. 4

    Watch every connection

    An expired token sends no error until the next run fails.

    Once a day, for every customer instance, check each connection with
    the same harmless read.
    
    On a failure, find out why: expired, revoked, the user deactivated, or
    a permission removed. Then:
    
      Mark the instance as needing attention in our product
      Email the customer's admin with what happened and one reconnect
      link that opens the same sign-in
      If nothing changes in three days, tell the account owner in Slack
    
    Never retry a sign-in on the customer's behalf, and never switch their
    instance to somebody else's connection.

    Most broken connections trace back to the person who connected leaving the customer's company. Show the connected user on your integrations page so the customer can spot it first.

What it connects to

Your product owns the screen. The customer owns the account.

Salesforce

The customer signs in through your own app registration, approves access, and the integration reads and writes with that connection only.

Reads and writes

HubSpot

The same pattern for every OAuth service a customer connects, each with its own app registration and permission check.

Reads and writes

SendGrid

Email the customer's admin when a connection stops working, with a link to reconnect.

Writes

Slack

Tell the account owner when a customer's connection has been broken for three days.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, Microsoft Teams, Marketo, Google Chat or Braze.

Connections in this build

Field mapping, templates and common problems for each pairing: HubSpot + Salesforce, SendGrid + Salesforce, SendGrid + HubSpot and Salesforce + Slack.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This holds your customers' access to their own systems. It is the part their security team will ask about.

Credentials belong to the customer

Each connection is stored against the customer's own user and used only by their instances. Your staff never see the token.

No other vendor on the screen

Your app registration, your domain, your styling. The customer sees your product all the way through.

Broken connections are found first by you

A daily check of every connection, so the customer hears from you before their data is wrong.

Every sign-in is recorded

Who connected, when, as which user and with which permissions, so a customer's question can be answered from the record.

Questions people ask

Will customers see Tray on the sign-in screen?

Not if you register your own OAuth app with each service and use your own subdomain for the sign-in. The approval screen then names your product.

Can our support team see a customer's credentials?

No. Connections are stored against the customer's own user and used only by their instances. Support can see that a connection exists and whether it works.

What happens when a customer's connection expires?

A daily check finds it, the instance is marked as needing attention in your product, and the customer's admin gets an email with a link to reconnect. The sync stays stopped until they do.

Why check permissions after sign-in?

Because a customer can untick a permission on the approval screen, and the sign-in still succeeds. A harmless read of each record type proves the access works before anything depends on it.

Last reviewed October 2026.