api-integration-builder

Build reliable third-party API integrations including OAuth, webhooks, rate limiting, error handling, and data sync. Use when integrating with external services (Slack, Stripe, Gmail, etc.), building API connections, handling webhooks, or implementing OAuth flows.

16 stars

Best use case

api-integration-builder is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Build reliable third-party API integrations including OAuth, webhooks, rate limiting, error handling, and data sync. Use when integrating with external services (Slack, Stripe, Gmail, etc.), building API connections, handling webhooks, or implementing OAuth flows.

Teams using api-integration-builder should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/api-integration-builder/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/backend/api-integration-builder/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/api-integration-builder/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How api-integration-builder Compares

Feature / Agentapi-integration-builderStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Build reliable third-party API integrations including OAuth, webhooks, rate limiting, error handling, and data sync. Use when integrating with external services (Slack, Stripe, Gmail, etc.), building API connections, handling webhooks, or implementing OAuth flows.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# API Integration Builder

Build reliable, maintainable integrations with third-party APIs.

## Core Principles

1. **Assume failure**: APIs will go down, rate limits will hit, data will be inconsistent
2. **Idempotency matters**: Retries shouldn't cause duplicate actions
3. **User experience first**: Never show users "API Error 429"
4. **Security always**: Tokens are secrets, validate all data, assume malicious input

## Integration Architecture

### Basic Integration Flow

```
Your App ←→ Integration Layer ←→ Third-Party API
            ├── Auth (OAuth, API keys)
            ├── Rate limiting
            ├── Retries
            ├── Error handling
            ├── Data transformation
            └── Webhooks (if supported)
```

### Components

1. **Authentication Layer**: Handle OAuth, refresh tokens, API keys
2. **Request Manager**: Make API calls with retries, rate limiting
3. **Webhook Handler**: Receive real-time updates from third parties
4. **Data Sync**: Keep your data in sync with external service
5. **Error Recovery**: Handle failures gracefully

## Authentication Patterns

### API Key Authentication

**Simple but limited**:

```typescript
interface APIKeyConfig {
  api_key: string
  api_secret?: string
}

class SimpleAPIClient {
  private apiKey: string

  async request(endpoint: string, options: RequestOptions) {
    return fetch(`https://api.service.com${endpoint}`, {
      ...options,
      headers: {
        Authorization: `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json'
      }
    })
  }
}
```

**Pros**: Simple, no complex flows
**Cons**: Can't act on behalf of users, no granular permissions

### OAuth 2.0 Flow

**The standard for user-authorized access**:

```typescript
// 1. Redirect user to authorize
app.get('/connect/slack', (req, res) => {
  const authUrl = new URL('https://slack.com/oauth/v2/authorize')
  authUrl.searchParams.set('client_id', SLACK_CLIENT_ID)
  authUrl.searchParams.set('redirect_uri', 'https://yourapp.com/auth/slack/callback')
  authUrl.searchParams.set('scope', 'channels:read,chat:write')
  authUrl.searchParams.set('state', generateSecureRandomString()) // CSRF protection

  res.redirect(authUrl.toString())
})

// 2. Handle callback
app.get('/auth/slack/callback', async (req, res) => {
  const { code, state } = req.query

  // Verify state to prevent CSRF
  if (state !== req.session.oauthState) {
    throw new Error('Invalid state')
  }

  // Exchange code for access token
  const tokenResponse = await fetch('https://slack.com/api/oauth.v2.access', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: SLACK_CLIENT_ID,
      client_secret: SLACK_CLIENT_SECRET,
      code: code,
      redirect_uri: 'https://yourapp.com/auth/slack/callback'
    })
  })

  const { access_token, refresh_token, expires_in } = await tokenResponse.json()

  // Store tokens securely (encrypted!)
  await db.storeIntegration({
    user_id: req.user.id,
    service: 'slack',
    access_token: encrypt(access_token),
    refresh_token: encrypt(refresh_token),
    expires_at: Date.now() + expires_in * 1000
  })

  res.redirect('/settings/integrations?success=slack')
})
```

**Token Refresh**:

```typescript
async function getValidAccessToken(userId: string, service: string) {
  const integration = await db.getIntegration(userId, service)

  // Token still valid?
  if (integration.expires_at > Date.now() + 60000) {
    // 1 min buffer
    return decrypt(integration.access_token)
  }

  // Refresh token
  const refreshResponse = await fetch('https://slack.com/api/oauth.v2.access', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: SLACK_CLIENT_ID,
      client_secret: SLACK_CLIENT_SECRET,
      grant_type: 'refresh_token',
      refresh_token: decrypt(integration.refresh_token)
    })
  })

  const { access_token, expires_in } = await refreshResponse.json()

  // Update stored tokens
  await db.updateIntegration(integration.id, {
    access_token: encrypt(access_token),
    expires_at: Date.now() + expires_in * 1000
  })

  return access_token
}
```

## Request Management

### Rate Limiting

**Client-side rate limiting**:

```typescript
import { RateLimiter } from 'limiter'

class RateLimitedAPIClient {
  private limiter: RateLimiter

  constructor(tokensPerInterval: number, interval: string) {
    this.limiter = new RateLimiter({
      tokensPerInterval,
      interval
    })
  }

  async request(endpoint: string, options: RequestOptions) {
    // Wait for rate limit token
    await this.limiter.removeTokens(1)

    return fetch(`https://api.service.com${endpoint}`, options)
  }
}

// Example: Slack allows ~1 request per second
const slackClient = new RateLimitedAPIClient(1, 'second')
```

**429 Response handling**:

```typescript
async function requestWithRetry(url: string, options: RequestOptions, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options)

    if (response.status === 429) {
      // Check Retry-After header
      const retryAfter = response.headers.get('Retry-After')
      const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000

      console.log(`Rate limited, waiting ${waitTime}ms`)
      await sleep(waitTime)
      continue
    }

    return response
  }

  throw new Error('Max retries exceeded')
}
```

### Error Handling

**Comprehensive error handling**:

```typescript
class APIError extends Error {
  constructor(
    public statusCode: number,
    public response: any,
    public retryable: boolean
  ) {
    super(`API Error: ${statusCode}`)
  }
}

async function safeAPIRequest(endpoint: string, options: RequestOptions) {
  try {
    const response = await fetch(endpoint, options)

    // Success
    if (response.ok) {
      return await response.json()
    }

    // Client errors (4xx) - usually not retryable
    if (response.status >= 400 && response.status < 500) {
      if (response.status === 401) {
        // Token expired, refresh and retry
        await refreshAccessToken()
        return safeAPIRequest(endpoint, options)
      }

      if (response.status === 429) {
        // Rate limited, retry with backoff
        throw new APIError(429, await response.json(), true)
      }

      // Other 4xx errors - don't retry
      throw new APIError(response.status, await response.json(), false)
    }

    // Server errors (5xx) - retryable
    if (response.status >= 500) {
      throw new APIError(response.status, await response.json(), true)
    }
  } catch (error) {
    if (error instanceof APIError) throw error

    // Network errors - retryable
    throw new APIError(0, { message: error.message }, true)
  }
}
```

**Exponential backoff**:

```typescript
async function retryWithBackoff<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn()
    } catch (error) {
      if (error instanceof APIError && !error.retryable) {
        throw error // Don't retry non-retryable errors
      }

      if (attempt === maxRetries - 1) {
        throw error // Last attempt failed
      }

      // Exponential backoff with jitter
      const delay = baseDelay * Math.pow(2, attempt) * (0.5 + Math.random() * 0.5)
      console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms`)
      await sleep(delay)
    }
  }

  throw new Error('Unreachable')
}

// Usage
const data = await retryWithBackoff(() => slackClient.postMessage('#general', 'Hello!'))
```

## Webhook Handling

### Receiving Webhooks

```typescript
interface WebhookPayload {
  event_type: string
  data: any
  timestamp: number
  signature: string
}

app.post('/webhooks/stripe', async (req, res) => {
  // 1. Verify signature (CRITICAL for security)
  const signature = req.headers['stripe-signature']
  let event: Stripe.Event

  try {
    event = stripe.webhooks.constructEvent(req.body, signature, STRIPE_WEBHOOK_SECRET)
  } catch (error) {
    console.error('⚠️ Webhook signature verification failed:', error.message)
    return res.status(400).send('Webhook signature verification failed')
  }

  // 2. Respond immediately (don't make webhook wait)
  res.status(200).send('Received')

  // 3. Process asynchronously
  await queue.add('process-webhook', {
    event_type: event.type,
    event_id: event.id,
    data: event.data
  })
})

// Process webhook in background job
async function processWebhook(job: Job) {
  const { event_type, event_id, data } = job.data

  // Idempotency check (handle duplicate webhooks)
  const existing = await db.webhookEvents.findOne({ event_id })
  if (existing) {
    console.log(`Webhook ${event_id} already processed`)
    return
  }

  // Mark as processing
  await db.webhookEvents.create({ event_id, status: 'processing' })

  try {
    switch (event_type) {
      case 'payment_intent.succeeded':
        await handlePaymentSuccess(data)
        break

      case 'customer.subscription.deleted':
        await handleSubscriptionCancelled(data)
        break

      // ... other event types
    }

    // Mark as completed
    await db.webhookEvents.update(event_id, { status: 'completed' })
  } catch (error) {
    // Mark as failed, will retry
    await db.webhookEvents.update(event_id, {
      status: 'failed',
      error: error.message,
      retry_count: (existing?.retry_count || 0) + 1
    })
    throw error // Let queue retry
  }
}
```

### Webhook Security

```typescript
// HMAC signature verification
function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expectedSignature = crypto.createHmac('sha256', secret).update(payload).digest('hex')

  // Constant-time comparison to prevent timing attacks
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))
}

// Timestamp validation (prevent replay attacks)
function validateWebhookTimestamp(timestamp: number, toleranceSeconds = 300) {
  const now = Math.floor(Date.now() / 1000)
  return Math.abs(now - timestamp) < toleranceSeconds
}
```

## Data Synchronization

### Sync Strategy

```typescript
interface SyncStrategy {
  // Full sync: Get all data from API
  fullSync(): Promise<void>

  // Incremental sync: Get only changed data since last sync
  incrementalSync(since: Date): Promise<void>

  // Real-time sync: Use webhooks for instant updates
  realTimeSync(webhookData: any): Promise<void>
}

class GoogleCalendarSync implements SyncStrategy {
  async fullSync() {
    const calendars = await googleCalendar.list()

    for (const calendar of calendars) {
      const events = await googleCalendar.events.list({
        calendarId: calendar.id,
        maxResults: 2500
      })

      await db.events.bulkUpsert(events)
    }
  }

  async incrementalSync(since: Date) {
    const events = await googleCalendar.events.list({
      updatedMin: since.toISOString(),
      showDeleted: true // Important: track deletions
    })

    for (const event of events) {
      if (event.status === 'cancelled') {
        await db.events.delete(event.id)
      } else {
        await db.events.upsert(event)
      }
    }
  }

  async realTimeSync(webhookData: any) {
    // Google sends channel notifications
    const { resourceId, resourceUri } = webhookData

    // Fetch the changed resource
    const event = await googleCalendar.events.get(resourceId)
    await db.events.upsert(event)
  }
}
```

### Sync Scheduler

```typescript
interface SyncJob {
  user_id: string
  service: string
  type: 'full' | 'incremental'
}

// Schedule sync jobs
async function scheduleSyncJobs() {
  // Full sync: Weekly for all active integrations
  cron.schedule('0 0 * * 0', async () => {
    const integrations = await db.integrations.findActive()

    for (const integration of integrations) {
      await queue.add('sync', {
        user_id: integration.user_id,
        service: integration.service,
        type: 'full'
      })
    }
  })

  // Incremental sync: Every 15 minutes
  cron.schedule('*/15 * * * *', async () => {
    const integrations = await db.integrations.findActive()

    for (const integration of integrations) {
      await queue.add('sync', {
        user_id: integration.user_id,
        service: integration.service,
        type: 'incremental'
      })
    }
  })
}

// Process sync job
async function processSyncJob(job: Job<SyncJob>) {
  const { user_id, service, type } = job.data

  const sync = getSyncStrategy(service)

  if (type === 'full') {
    await sync.fullSync()
  } else {
    const lastSync = await db.syncLog.getLastSync(user_id, service)
    await sync.incrementalSync(lastSync.completed_at)
  }

  await db.syncLog.create({
    user_id,
    service,
    type,
    completed_at: new Date()
  })
}
```

## Common Integration Patterns

### Slack Integration

```typescript
class SlackIntegration {
  async postMessage(channel: string, text: string, attachments?: any[]) {
    const accessToken = await getValidAccessToken(userId, 'slack')

    return await retryWithBackoff(() =>
      fetch('https://slack.com/api/chat.postMessage', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          channel,
          text,
          attachments
        })
      })
    )
  }

  async getChannels() {
    const accessToken = await getValidAccessToken(userId, 'slack')

    const response = await fetch('https://slack.com/api/conversations.list', {
      headers: { Authorization: `Bearer ${accessToken}` }
    })

    const data = await response.json()

    if (!data.ok) {
      throw new Error(`Slack API error: ${data.error}`)
    }

    return data.channels
  }
}
```

### Stripe Integration

```typescript
class StripeIntegration {
  async createSubscription(customerId: string, priceId: string) {
    try {
      const subscription = await stripe.subscriptions.create({
        customer: customerId,
        items: [{ price: priceId }],
        payment_behavior: 'default_incomplete',
        expand: ['latest_invoice.payment_intent'],
        metadata: {
          user_id: userId,
          plan: 'pro'
        }
      })

      return {
        subscription_id: subscription.id,
        client_secret: subscription.latest_invoice.payment_intent.client_secret
      }
    } catch (error) {
      if (error instanceof Stripe.errors.StripeError) {
        // Handle specific Stripe errors
        if (error.type === 'card_error') {
          throw new Error('Card was declined')
        }
      }
      throw error
    }
  }

  async cancelSubscription(subscriptionId: string) {
    // Cancel at period end (don't refund)
    await stripe.subscriptions.update(subscriptionId, {
      cancel_at_period_end: true
    })
  }
}
```

### Gmail/Google Calendar Integration

```typescript
import { google } from 'googleapis'

class GoogleIntegration {
  async sendEmail(to: string, subject: string, body: string) {
    const auth = await this.getOAuth2Client()
    const gmail = google.gmail({ version: 'v1', auth })

    const message = [`To: ${to}`, `Subject: ${subject}`, '', body].join('\n')

    const encodedMessage = Buffer.from(message)
      .toString('base64')
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=+$/, '')

    await gmail.users.messages.send({
      userId: 'me',
      requestBody: {
        raw: encodedMessage
      }
    })
  }

  async listCalendarEvents(calendarId: string, timeMin: Date, timeMax: Date) {
    const auth = await this.getOAuth2Client()
    const calendar = google.calendar({ version: 'v3', auth })

    const response = await calendar.events.list({
      calendarId,
      timeMin: timeMin.toISOString(),
      timeMax: timeMax.toISOString(),
      singleEvents: true,
      orderBy: 'startTime'
    })

    return response.data.items
  }
}
```

## Testing Integrations

### Mock External APIs

```typescript
// tests/mocks/stripe.ts
export class MockStripe {
  subscriptions = {
    create: jest.fn().mockResolvedValue({
      id: 'sub_123',
      status: 'active'
    }),

    cancel: jest.fn().mockResolvedValue({
      id: 'sub_123',
      status: 'canceled'
    })
  }
}

// tests/integration.test.ts
describe('Stripe Integration', () => {
  let stripeIntegration: StripeIntegration

  beforeEach(() => {
    stripe = new MockStripe()
    stripeIntegration = new StripeIntegration(stripe)
  })

  it('creates a subscription', async () => {
    const result = await stripeIntegration.createSubscription('cus_123', 'price_123')

    expect(result.subscription_id).toBe('sub_123')
    expect(stripe.subscriptions.create).toHaveBeenCalledWith({
      customer: 'cus_123',
      items: [{ price: 'price_123' }]
      // ...
    })
  })

  it('handles card errors gracefully', async () => {
    stripe.subscriptions.create.mockRejectedValue(
      new Stripe.errors.StripeCardError('Card declined')
    )

    await expect(stripeIntegration.createSubscription('cus_123', 'price_123')).rejects.toThrow(
      'Card was declined'
    )
  })
})
```

### Webhook Testing

```typescript
// Generate valid webhook signatures for testing
function generateTestWebhook(payload: any, secret: string) {
  const timestamp = Math.floor(Date.now() / 1000)
  const signature = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${JSON.stringify(payload)}`)
    .digest('hex')

  return {
    payload,
    headers: {
      'stripe-signature': `t=${timestamp},v1=${signature}`
    }
  }
}

describe('Webhook Handler', () => {
  it('processes valid webhook', async () => {
    const webhook = generateTestWebhook(
      {
        type: 'payment_intent.succeeded',
        data: {
          /* ... */
        }
      },
      STRIPE_WEBHOOK_SECRET
    )

    const response = await request(app)
      .post('/webhooks/stripe')
      .set(webhook.headers)
      .send(webhook.payload)

    expect(response.status).toBe(200)
    // Verify processing happened
  })

  it('rejects invalid signature', async () => {
    const response = await request(app)
      .post('/webhooks/stripe')
      .set({ 'stripe-signature': 'invalid' })
      .send({ type: 'payment_intent.succeeded' })

    expect(response.status).toBe(400)
  })
})
```

## Monitoring & Observability

### Integration Health Checks

```typescript
interface IntegrationHealth {
  service: string
  status: 'healthy' | 'degraded' | 'down'
  last_success: Date
  last_failure?: Date
  error_rate_24h: number
}

async function checkIntegrationHealth(service: string): Promise<IntegrationHealth> {
  const logs = await db.integrationLogs.findRecent(service, '24h')

  const total = logs.length
  const failures = logs.filter(l => l.status === 'failed').length
  const errorRate = failures / total

  let status: 'healthy' | 'degraded' | 'down'
  if (errorRate < 0.01) status = 'healthy'
  else if (errorRate < 0.1) status = 'degraded'
  else status = 'down'

  return {
    service,
    status,
    last_success: logs.find(l => l.status === 'success')?.timestamp,
    last_failure: logs.find(l => l.status === 'failed')?.timestamp,
    error_rate_24h: errorRate
  }
}
```

### Logging & Alerts

```typescript
// Log all API requests
async function logAPIRequest(
  service: string,
  endpoint: string,
  statusCode: number,
  duration: number,
  error?: Error
) {
  await db.apiLogs.create({
    service,
    endpoint,
    status_code: statusCode,
    duration_ms: duration,
    error: error?.message,
    timestamp: new Date()
  })

  // Alert on high error rates
  if (statusCode >= 500) {
    const recentErrors = await db.apiLogs.count({
      service,
      status_code: { $gte: 500 },
      timestamp: { $gte: new Date(Date.now() - 5 * 60 * 1000) } // Last 5 min
    })

    if (recentErrors > 10) {
      await sendAlert({
        title: `High error rate for ${service} integration`,
        message: `${recentErrors} errors in last 5 minutes`
      })
    }
  }
}
```

## User Experience

### Integration Status UI

```typescript
interface IntegrationStatus {
  connected: boolean
  last_sync: Date
  sync_in_progress: boolean
  error?: string
}

// Show integration status to user
<Card>
  <IntegrationIcon service="slack" />
  <div>
    <h3>Slack</h3>
    {status.connected ? (
      <>
        <Badge color="green">Connected</Badge>
        <p>Last synced {formatRelative(status.last_sync)}</p>
        {status.sync_in_progress && <Spinner />}
      </>
    ) : (
      <>
        <Badge color="red">Disconnected</Badge>
        {status.error && <p className="error">{status.error}</p>}
        <Button onClick={reconnect}>Reconnect</Button>
      </>
    )}
  </div>
  <Button variant="secondary" onClick={disconnect}>
    Disconnect
  </Button>
</Card>
```

## Quick Start Checklist

### Setting Up Your First Integration

- [ ] Choose integration type (OAuth vs API key)
- [ ] Register OAuth app (get client ID/secret)
- [ ] Implement authentication flow
- [ ] Store tokens securely (encrypted)
- [ ] Implement token refresh
- [ ] Add rate limiting
- [ ] Add error handling with retries
- [ ] Set up webhook endpoint (if available)
- [ ] Add webhook signature verification
- [ ] Implement idempotency for webhooks
- [ ] Add monitoring & logging
- [ ] Test thoroughly (including failures)

## Common Pitfalls

❌ **Storing tokens unencrypted**: Always encrypt access/refresh tokens
❌ **No token refresh**: Tokens expire, implement refresh flow
❌ **Synchronous webhook processing**: Process webhooks in background jobs
❌ **No idempotency**: Webhooks may be delivered multiple times
❌ **Ignoring rate limits**: Implement client-side rate limiting
❌ **Poor error messages**: Show helpful errors, not "API Error 500"
❌ **No retry logic**: APIs are unreliable, always retry with backoff
❌ **Missing signature verification**: Attackers can forge webhooks

## Summary

Great API integrations:

- ✅ Handle auth flows properly (OAuth, refresh tokens)
- ✅ Respect rate limits
- ✅ Retry transient failures with exponential backoff
- ✅ Verify webhook signatures
- ✅ Process webhooks idempotently
- ✅ Monitor health and error rates
- ✅ Show clear status to users
- ✅ Store credentials securely

Related Skills

jira-integration

16
from diegosouzapw/awesome-omni-skill

Agent Skill: Comprehensive Jira integration through lightweight Python scripts. AUTOMATICALLY TRIGGER when user mentions Jira URLs like 'https://jira.*/browse/*', 'https://*.atlassian.net/browse/*', or issue keys like 'PROJ-123'. Use when searching issues (JQL), getting/updating issue details, creating issues, transitioning status, adding comments, logging worklogs, managing sprints and boards, creating issue links, or formatting Jira wiki markup. If authentication fails, offer to configure credentials interactively. Supports both Jira Cloud and Server/Data Center with automatic authentication detection. By Netresearch.

Directus AI Assistant Integration

16
from diegosouzapw/awesome-omni-skill

Build AI-powered features in Directus: chat interfaces, content generation, smart suggestions, and copilot functionality

ai-integration

16
from diegosouzapw/awesome-omni-skill

AI/LLM integration patterns - Claude API, fal.ai, streaming, tool use

agent-builder

16
from diegosouzapw/awesome-omni-skill

Build AI agents using pai-agent-sdk with Pydantic AI. Covers agent creation via create_agent(), toolset configuration, session persistence with ResumableState, subagent hierarchies, and browser automation. Use when creating agent applications, configuring custom tools, managing multi-turn sessions, setting up hierarchical agents, or implementing HITL approval flows.

accessibility-object-model-integration

16
from diegosouzapw/awesome-omni-skill

Programmatic manipulation of the accessibility tree to support complex custom controls in React.

academic-data-integration

16
from diegosouzapw/awesome-omni-skill

When the user needs to integrate multiple data sources (Canvas API, user memory, file systems) to create comprehensive academic reports. This skill combines course information, assignment details, submission status, and user context to generate actionable insights. Triggers include requests that involve cross-referencing multiple data sources or creating consolidated academic reports from disparate systems.

302ai-api-integration

16
from diegosouzapw/awesome-omni-skill

ALWAYS use this skill when user needs ANY API functionality (AI models, image generation, video, audio, text processing, etc.). Automatically search 302.AI's 1400+ APIs and generate integration code. Use proactively whenever APIs or AI capabilities are mentioned.

1k-defi-module-integration

16
from diegosouzapw/awesome-omni-skill

Interactive guide for integrating new DeFi modules or protocols into OneKey. Use when adding new DeFi features like staking protocols, lending markets, or entirely new DeFi modules. Triggers on DeFi, protocol, integration, Earn, Borrow, staking, lending, supply, borrow, withdraw, repay, claim, new module, Pendle, Aave, Compound.

workflow-integration-git

16
from diegosouzapw/awesome-omni-skill

Git commit workflow with conventional commits, artifact cleanup, and optional push/PR creation

Project Setup and CCAGI Integration

16
from diegosouzapw/awesome-omni-skill

Complete project initialization including Node.js/TypeScript setup, GitHub integration, and CCAGI framework integration. Use when creating new projects or integrating CCAGI components.

integrations

16
from diegosouzapw/awesome-omni-skill

NextDNS integration guides for third-party platforms and services. This skill should be used when integrating NextDNS with routers, home automation systems, network management platforms, or other third-party services. Triggers on tasks involving Tailscale, Home Assistant, Ubiquiti, pfSense, OpenWrt, or other platform-specific NextDNS configurations.

integration-workflows

16
from diegosouzapw/awesome-omni-skill

Cross-MCP workflows that coordinate multiple systems (Linear, GitHub, n8n, Slack) for end-to-end automation. Captures patterns that span tool boundaries.