Last updated on October 23, 2026
Connecting an end customer
Send an end customer a link so they connect their account on a platform, then check they are connected.
How connecting works
Before calls can work for an end customer, they connect their account on that platform once. Any platform switched on for your company can be connected, and the end customer approves your own app there. Your product asks for a link, shows it to the end customer, and they approve on the platform.
Ask for a link
Call connections.createLink. The link works once and expires after 15 minutes. Opening it does not use it up: it is used when the end customer presses Connect, so a mail scanner or a link preview opening it first does no harm.
Send the end customer to the link
They log in to the platform and approve.
They land on your return address
When they are done, they land on your returnUrl with status=connected, or with status=failed and a reason.
Confirm with connections.get
The connection is written before the end customer lands, so the answer is already there.
const link = await appnigma.connections.createLink({
endCustomerId: "lawfirm-123",
platform: "hubspot",
returnUrl: "https://app.example.com/integrations/hubspot/done",
});
console.log("send the end customer to", link.url, "before", link.expiresAt);
const connection = await appnigma.connections.get({ endCustomerId: "lawfirm-123", platform: "hubspot" });
if (connection.status === "connected") {
console.log("ready to post and pull");
}link = client.connections.create_link(
end_customer_id: "lawfirm-123",
platform: "hubspot",
return_url: "https://app.example.com/integrations/hubspot/done"
)
puts "send the end customer to #{link[:url]} before #{link[:expires_at]}"
connection = client.connections.get(end_customer_id: "lawfirm-123", platform: "hubspot")
puts "ready to post and pull" if connection[:status] == "connected"link = client.connections.create_link(
end_customer_id="lawfirm-123",
platform="hubspot",
return_url="https://app.example.com/integrations/hubspot/done",
)
print(f"send the end customer to {link['url']} before {link['expires_at']}")
connection = client.connections.get(end_customer_id="lawfirm-123", platform="hubspot")
if connection["status"] == "connected":
print("ready to post and pull")An end customer who is already connected can open a new link to connect again, for example after changing HubSpot accounts.
Make a link: connections.createLink
In Ruby and Python the call is connections.create_link. Names are shown as in TypeScript; Ruby and Python use the same names in snake case: end_customer_id, return_url, expires_at.
Your own id for your customer. 1 to 100 characters of letters, digits, dot, dash or underscore.
The platform to connect, such as hubspot. It must be switched on for your company.
Where the end customer lands when they are done. It must be HTTPS, and at most 2048 bytes when written as a JSON string: about 2046 plain characters.
The link to send the end customer to.
When the link stops working, 15 minutes after it was made.
createLink is made once and never tried again. Every call makes a new link, and a repeat after a lost answer would leave a working link nobody saw. If it fails, decide in your code whether to call again.
Where the end customer lands
The end customer lands on your returnUrl with status added to the address:
status | Meaning |
|---|---|
connected | They approved. Calls for them can start. |
failed | They did not connect. reason says why. |
reason | Meaning |
|---|---|
link_expired | The link expired before it was used. Make a new one. |
declined | The end customer did not approve. |
account_taken | That platform account already belongs to another of your end customers on this platform. A new link will not fix it. |
failed | The platform would not confirm the account, or something else went wrong. |
Check a connection: connections.get
Your own id for your customer.
The platform, such as hubspot.
The id you asked about.
The platform you asked about.
connected, needs_reconnect or disconnected.
An end customer the API has never seen on that platform is a not-found error, not a status: SdkNotFoundError in TypeScript, Appnigma::NotFoundError in Ruby, NotFoundError in Python.
The id travels in the address for this call, so an id that is only . or .. is refused before the call is made: SdkInputError in TypeScript, Appnigma::InputError in Ruby, InputError in Python. An address drops those, and the request would reach the wrong place. Do not use them as end customer ids.
connections.get is tried again only when that is safe, up to three times by default. See Retries and time limits.