Introduction to the App SDK
An overview of the functionality provided by the App SDK
This only covers apps from the perspective of the App SDK, apps can also use the REST API
An app is a way to extend the existing functionality of Attio, typically by pulling data into Attio from a third party source, or of extracting data out of Attio to use with some tool. Apps can provide custom UI directly inside of Attio’s user interface using custom React components.
Let’s look at an example.
Let’s imagine a hypothetical service called Acme Lead Checker (ALC) that has an API to receive potential leads, an AI agent initiates an SMS chat with the lead, and then needs to update the lead’s record in Attio about how interested the person is in whatever product we are selling.
Our app needs:
- A button inside Attio that will call a server function
- A server function to actually send the data to ALC
- A webhook to receive the lead status back from ALC sometime in the future
App UI components cannot directly communicate with the outside world. They can
only call custom app server functions, which can communicate with the outside
world via fetch()
, and communicate
with Attio’s REST API via attioFetch()
.
Sequence
The general sequence of how the app will work is:
Installation
- User clicks to install the app.
- User is prompted to add a connection to Acme Lead Checker
- User logs into Acme Lead Checker to complete the OAuth flow.
- User is redirected back to Attio. The app is now installed.
- The
connection-added
event handler the app registered is fired. - Event Handler calls
createWebhookHandler()
to register a webhook handler. - Event Handler registers the new webhook with Acme Lead Checker.
Usage
- App provides a record action which will manifest
itself in Attio’s UI as
- a button on the People record page
- in the CMD-K quick action palette.
- User views the record page
- User clicks button
- Attio’s UI fires the
onTrigger()
function provided by the record action - Record Action notifies the user that async things are happening
with
showToast()
. - Record Action loads the phone number of the person whose record page we are on
asynchronously via GraphQL using
runQuery()
.- If no phone numbers are found, the user is notified via an
alert()
. Otherwise…
- If no phone numbers are found, the user is notified via an
- Record Action calls a
server function called
sendToALC()
. - Server function uses
fetch()
to send aPOST
request toapi.acmeleadchecker.ai
. - Server function uses
attioFetch()
to mark the record as “Pending”. - Server function returns success.
- Record Action hides first toast
with
hideToast()
. - Record Action notifies the user that the process was successful
with
showToast()
.
…some time later…
- Acme Lead Checker’s server calls a webhook provided by the app.
- Webhook Handler uses
attioFetch()
to mark the record as “Complete”.
Implementation
Record action
Record action files can have any name, but they
MUST have a named export called recordAction
.
GraphQL query
Now let’s write that GraphQL query we’re importing.
Server function
Server function file names MUST:
- have a
.server.ts
(or.server.js
) suffix - contain an
export default async function
The suffix is how Attio knows to execute them on the server. However, they are imported as if they were in the same bundle as the client side code, even though they are not.
Because they live in different bundles and runtimes, everything passed to, returned from, or thrown by server functions MUST be serializable.
Webhook handler
Our webhook handler is going to be called by Acme Lead Checker when they have processed our lead that we sent them.
Webhook handler files MUST:
- Live under the
src/webhooks
directory - Have a
.webhook.ts
(or.webhook.js
) suffix. - Contain an
export default async function
that:
Connection event handlers
In order to let Acme Lead Checker know how to call our app’s webhook, we need to tell them as soon as our user creates an authorized connection; we accomplish this with event handlers.
Connection Event Handler files MUST:
- Live in
src/events
- Have a
.event.ts
(or.event.js
) suffix. - Contain an
export default async function
that:- Takes a
{ connection: Connection }
argument - Returns
void
- Takes a
Connection added event handler
When a connection is added, we need to:
- Create a webhook
- Register our webhook with Acme Lead Checker
- Update our webhook with the unique identifier of our webhook on ALC’s side
Connection removed event handler
When a connection is removed, we need to:
- Load all our app’s webhook handlers (there should only be one)
- For each handler, tell ALC to stop calling it
- Delete the webhook from Attio
Was this page helpful?