Connectors
Unipile
Unipile's hosted auth links, connected LinkedIn, WhatsApp and mail accounts, chats, messages and email, with webhooks when the other side writes back.
danwo's Unipile emulator answers every *.unipile.com DSN your app is given, and the hosted auth
pages on account.unipile.com. unipile-node-sdk works against it unchanged: your app links a
user's LinkedIn or WhatsApp, then reads and sends messages through it.
Set up
Add unipileService with your access token and a connected account. Point the app at any DSN:
import { appEnvironment, defineConfig, unipileService } from "@danwo/sdk"
const url = "http://localhost:3000"
const token = "danwo-unipile-token"
export default defineConfig({
testDir: "tests",
readiness: { mode: "page+backend", settle: true },
environment: () =>
appEnvironment({
app: {
command: "npm run dev",
url,
env: { UNIPILE_ACCESS_TOKEN: token, UNIPILE_DSN: "api1.unipile.com:13111" },
},
services: [
unipileService({
seed: {
tokens: [token],
accounts: [{ id: "acc_ada", type: "LINKEDIN", name: "Ada Lovelace", username: "ada" }],
webhooks: [{ source: "messaging", url: `${url}/api/webhooks/unipile` }],
},
}),
],
}),
})Every call needs the token in X-API-KEY, as on Unipile.
Seed it
| Field | What it seeds |
|---|---|
tokens | Access tokens the API accepts. |
accounts | Connected LinkedIn, WhatsApp, Google or mail accounts. |
webhooks | Where messaging, email and account events go, with your own auth headers. |
Use it in a test
Have a contact write to the user on LinkedIn, then check the app shows it:
import { type UnipileFixtures, test as base, unipileWorkspace } from "@danwo/sdk"
const test = base.extend<UnipileFixtures>()
test("shows a new LinkedIn message", async ({ app, screen, expect, settle, unipile }) => {
unipileWorkspace(unipile).receive(
"acc_ada",
{ providerId: "bob", name: "Bob" },
"Free for a call?",
)
await settle()
await app.open("/inbox")
await expect(screen.getByText("Free for a call?")).toBeVisible()
})unipileWorkspace(unipile) | What it's for |
|---|---|
accounts() | The connected accounts. |
messages(id), emails(id) | An account's messages and email. |
receive(…), receiveEmail(…) | Write to the user, as the other side. |
disconnect(id) | Drop an account, as when its credentials expire. |
What's covered
| Area | Covered |
|---|---|
| Accounts | Hosted auth links and pages; listing and removing accounts. |
| Messaging | Chats, attendees and messages: read, start a chat, send. |
| Reading and sending email. | |
| Users | Profiles, posts and the signed-in user. |
| Webhooks | Webhook subscriptions. |
Faults
| Call | Faults the matrix tries |
|---|---|
A send, such as POST …/chats/:id/messages | 429, 401 for a disconnected account, a 30-second delay, 500, connection reset, answer lost after Unipile sent it |
| A read | 401, 500, connection reset |
| Every webhook delivery | arrives twice, arrives 10 minutes late, forged, 1 hour stale |
Webhooks
Events go to each subscription's URL with the headers you gave it, as Unipile sends them:
message_received for messaging, mail_received for email, and account_status when an
account connects or disconnects.
Fidelity
Live, reads only. danwo fidelity unipile runs 2 scenarios against a real workspace: an
unknown token, and listing accounts. Both match.
Not covered yet
- Instagram, Telegram and X accounts
- LinkedIn invitations, searches and Sales Navigator
- Attachments and voice notes
Next
Nango
Nango integrations, connect sessions with the hosted Connect UI, connections whose tokens refresh, the proxy, actions and records, routed to danwo's other emulators.
Pusher
Pusher Channels, the API your server triggers events on and the socket pusher-js keeps open, with private and presence channels, subscription counting, signed webhooks and Beams.