authkit

Add OAuth connections for 200+ platforms (Gmail, Slack, HubSpot, etc.) with Pica's drop-in AuthKit widget

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "authkit" with this command: npx skills add picahq/skills/picahq-skills-authkit

Pica AuthKit Integration Guide

Complete guide for integrating Pica AuthKit to enable users to connect third-party tools (Gmail, Slack, HubSpot, etc.) in your application.

What is AuthKit?

AuthKit is a drop-in OAuth component that:

  • Provides pre-built UI for 200+ integration OAuth flows
  • Handles token management and refresh automatically
  • Works with any frontend framework (React, Vue, vanilla JS)
  • Requires a backend token endpoint

Prerequisites


Architecture Overview

┌─────────────┐     ┌─────────────────┐     ┌─────────────┐
│   Frontend  │────▶│  Your Backend   │────▶│  Pica API   │
│  (AuthKit)  │     │ (Token Endpoint)│     │             │
└─────────────┘     └─────────────────┘     └─────────────┘
       │                                           │
       └───────────── OAuth Flow ──────────────────┘
  1. Frontend calls your token endpoint
  2. Your backend generates a Pica session token
  3. AuthKit uses token to manage OAuth flow
  4. On success, you receive connection details to store

Step 1: Install Packages

Frontend:

npm install @picahq/authkit

Backend:

npm install @picahq/authkit-token

Step 2: Backend Token Endpoint

Create an endpoint that generates AuthKit session tokens.

Requirements

  • Must accept POST requests
  • Must return token object directly (not wrapped)
  • Must include CORS headers (AuthKit iframe calls this endpoint)
  • Should identify the user via header or body parameter

Token Generation

import { AuthKitToken } from "@picahq/authkit-token";

const authKitToken = new AuthKitToken(PICA_SECRET_KEY);

const token = await authKitToken.create({
  identity: userId,      // Your user's unique identifier
  identityType: "user",  // "user" | "team" | "organization" | "project"
});

// Return token directly
return token;

Identity Types

TypeUse Case
userPersonal connections per user
teamShared connections within a team
organizationCompany-wide shared connections
projectProject-scoped isolated connections

Required CORS Headers

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, x-user-id

Important: Include any custom headers you use (like x-user-id) in the allowed headers.

Example Response

The token endpoint should return the token object directly:

{
  "token": "akt_xxxxx...",
  "expiresAt": "2024-01-01T00:00:00Z"
}

Step 3: Frontend Integration

Using the React Hook

import { useAuthKit } from "@picahq/authkit";

function ConnectButton() {
  const { open, isLoading } = useAuthKit({
    token: {
      url: "https://your-domain.com/api/authkit/token", // MUST be full URL
      headers: {
        "x-user-id": currentUserId,
      },
    },
    selectedConnection: "Gmail",  // Optional: skip list, go directly to this integration
    onSuccess: (connection) => {
      // connection.key - unique identifier for this connection
      // connection.platform - e.g., "gmail"
      // connection.environment - "live" or "test"
      // connection.state - "operational", "degraded", "failed", "unknown"

      saveConnectionToDatabase(connection);
    },
    onError: (error) => {
      console.error("Connection failed:", error);
    },
    onClose: () => {
      console.log("Modal closed");
    },
  });

  return (
    <button onClick={() => open()} disabled={isLoading}>
      Connect Integration
    </button>
  );
}

Critical: Token URL Must Be Full URL

// CORRECT - Full URL
url: "https://your-domain.com/api/authkit/token"
url: `${window.location.origin}/api/authkit/token`

// INCORRECT - Will fail
url: "/api/authkit/token"

selectedConnection Parameter

Pass the integration's display name to skip the integration list:

// Opens directly to Gmail auth flow
selectedConnection: "Gmail"

// Opens directly to Slack auth flow
selectedConnection: "Slack"

// Opens to integration list (user picks)
selectedConnection: undefined

Note: Use the display name (e.g., "Gmail", "Google Calendar", "HubSpot"), not the platform ID.


Step 4: Store Connections

When onSuccess fires, save the connection to your database.

Connection Object Structure

interface Connection {
  key: string;          // "live::gmail::default::abc123" - use this for API calls
  platform: string;     // "gmail"
  environment: string;  // "live" or "test"
  state: string;        // "operational", "degraded", "failed", "unknown"
}

Recommended Database Schema

CREATE TABLE user_connections (
    id UUID PRIMARY KEY,
    user_id TEXT NOT NULL,           -- Your user identifier
    platform TEXT NOT NULL,          -- "gmail", "slack", etc.
    connection_key TEXT UNIQUE,      -- Pica connection key
    environment TEXT DEFAULT 'live', -- "live" or "test"
    state TEXT DEFAULT 'operational',
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

Save on Success

onSuccess: async (connection) => {
  await fetch("/api/connections", {
    method: "POST",
    body: JSON.stringify({
      user_id: currentUserId,
      platform: connection.platform,
      connection_key: connection.key,
      environment: connection.environment,
      state: connection.state,
    }),
  });

  refreshConnectionsList();
}

Step 5: List Available Integrations

Fetch available integrations from Pica API.

API Request

GET https://api.picaos.com/v1/available-connectors?authkit=true&limit=300
Headers:
  x-pica-secret: YOUR_PICA_SECRET_KEY

Response Structure

{
  "rows": [
    {
      "platform": "gmail",
      "name": "Gmail",
      "category": "Communication",
      "image": "https://...",
      "description": "..."
    }
  ],
  "total": 200,
  "pages": 1,
  "page": 1
}

Key Fields

FieldDescription
platformPlatform identifier (use for API calls)
nameDisplay name (use for selectedConnection)
categoryCategory for grouping
imageLogo URL

Step 6: Using Connections

Once stored, use the connection_key to make API calls via Pica.

Passthrough API

POST https://api.picaos.com/v1/passthrough/{platform}/{action}
Headers:
  x-pica-secret: YOUR_PICA_SECRET_KEY
  x-pica-connection-key: CONNECTION_KEY_FROM_DATABASE
  Content-Type: application/json

Example: Send Gmail

const response = await fetch(
  "https://api.picaos.com/v1/passthrough/gmail/messages/send",
  {
    method: "POST",
    headers: {
      "x-pica-secret": PICA_SECRET_KEY,
      "x-pica-connection-key": user.gmailConnectionKey,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: "recipient@example.com",
      subject: "Hello",
      body: "Message content",
    }),
  }
);

Local Development

Chrome Security Flag

Chrome may block the AuthKit iframe from calling localhost. To fix:

  1. Go to chrome://flags
  2. Search for "Block insecure private network requests"
  3. Set to Disabled
  4. Restart Chrome

Alternative: Use ngrok

Expose your local server via ngrok and use that URL for the token endpoint.


Troubleshooting

IssueCauseSolution
405 Method Not AllowedMissing OPTIONS handlerAdd OPTIONS endpoint with CORS headers
CORS errorMissing or wrong CORS headersInclude all custom headers in Access-Control-Allow-Headers
Token fetch failsInvalid PICA_SECRET_KEYVerify key at app.picaos.com/settings/api-keys
Opens list instead of integrationWrong selectedConnection valueUse display name ("Gmail") not platform ID ("gmail")
Connection not savingonSuccess not storing dataSave connection in onSuccess callback
Foreign key erroruser_id references non-existent userRemove foreign key constraint or ensure user exists

API Reference

Token Generation

import { AuthKitToken } from "@picahq/authkit-token";
const token = new AuthKitToken(secretKey);
await token.create({ identity, identityType });

Frontend Hook

import { useAuthKit } from "@picahq/authkit";
const { open, isLoading } = useAuthKit({ token, onSuccess, onError, onClose, selectedConnection });

Pica API Endpoints

  • Available Connectors: GET /v1/available-connectors?authkit=true
  • List Connections: GET /v1/vault/connections?identity={id}&identityType=user
  • Passthrough: POST /v1/passthrough/{platform}/{action}

Documentation

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

pica

No summary provided by upstream source.

Repository SourceNeeds Review
General

openclaw-integrations

No summary provided by upstream source.

Repository SourceNeeds Review
General

integration-logos

No summary provided by upstream source.

Repository SourceNeeds Review
General

pica-mastra

No summary provided by upstream source.

Repository SourceNeeds Review