Receber por email
← Voltar para o catálogo

Abnormal Security API Patterns

Use this skill when working with the Abnormal Security REST API - Bearer token authentication, base URLs, rate limiting, pagination, OData filtering, error handling, and common API patterns. Covers token management, request/response formats, and integration best practices. Essential for developers and MSP administrators integrating with the Abnormal Security API.

31estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: Apache-2.0

Como adicionar

/plugin marketplace add wyre-technology/msp-claude-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/abnormal-security-api-patterns/svg)](https://www.skillteca.com.br/skills/abnormal-security-api-patterns)

Skills relacionadas

Ver todas de Automação →

Alerta por categoria

Receba novas skills de Automação toda segunda

1 email curto, só com as skills novas de Automação. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Abnormal Security REST API Patterns

Overview

The Abnormal Security REST API provides programmatic access to threat detection, abuse mailbox cases, account takeover protection, vendor risk assessment, and message analysis. This skill covers authentication, request patterns, pagination, filtering, rate limiting, error handling, and performance optimization.

Authentication

Bearer Token Authentication

Abnormal Security uses a static Bearer token for API authentication:

GET https://api.abnormalplatform.com/v1/threats
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json

Token Management

| Field | Description | |-------|-------------| | Type | Static API token (no expiry rotation required) | | Format | Long alphanumeric string | | Header | Authorization: Bearer <token> | | Scope | Full API access (determined at token creation) |

Environment Variables

export ABNORMAL_API_TOKEN="your-api-token"
export ABNORMAL_MCP_URL="https://mcp.wyre.ai/v1/abnormal-security/mcp"

MCP Gateway Headers

When used through the MCP Gateway, credentials are passed via the Authorization header:

{
  "headers": {
    "Authorization": "Bearer ${ABNORMAL_API_TOKEN}"
  }
}

The gateway forwards this header to the Abnormal Security MCP server, which uses it to authenticate with the Abnormal API.

Base URL

| Environment | Base URL | |-------------|----------| | Production | https://api.abnormalplatform.com |

API Paths

| Service | Path | Description | |---------|------|-------------| | Threats | /v1/threats | Threat detection data | | Threat Details | /v1/threats/{threatId} | Individual threat details | | Cases | /v1/cases | Abuse mailbox cases | | Case Details | /v1/cases/{caseId} | Individual case details | | Account Takeover | /v1/account-takeover/cases | ATO cases | | Vendors | /v1/vendors | VendorBase vendor risk | | Messages | /v1/threats/{threatId}/messages | Messages for a threat |

Request Patterns

Standard GET Request

GET /v1/threats?pageSize=25&pageNumber=1
Authorization: Bearer <token>
Accept: application/json

GET with OData Filter

GET /v1/threats?filter=attackType eq 'BEC'&pageSize=25
Authorization: Bearer <token>
Accept: application/json

Standard Response Format

{
  "threats": [
    {
      "threatId": "184def76-3c28-4e1b-9ef0-a5abc123def4",
      "attackType": "BEC",
      "attackStrategy": "Invoice/Payment Fraud",
      "sentTime": "2026-03-25T14:30:00Z"
    }
  ],
  "pageNumber": 1,
  "total": 142,
  "nextPageNumber": 2
}

Pagination

Cursor-Based Pagination

Abnormal Security uses page-number-based pagination:

GET /v1/threats?pageSize=25&pageNumber=1

Response:

{
  "threats": [...],
  "pageNumber": 1,
  "total": 142,
  "nextPageNumber": 2
}

Pagination Parameters

| Parameter | Type | Description | Default | Maximum | |-----------|------|-------------|---------|---------| | pageSize | int | Results per page | 25 | 100 | | pageNumber | int | Page number (1-based) | 1 | - |

Pagination Pattern

async function fetchAllPages(endpoint, params = {}) {
  const allItems = [];
  let pageNumber = 1;
  const pageSize = 100;
  let hasMore = true;

  while (hasMore) {
    const url = new URL(endpoint, 'https://api.abnormalplatform.com');
    url.searchParams.set('pageSize', pageSize.toString());
    url.searchParams.set('pageNumber', pageNumber.toString());
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));

    const response = await fetch(url, {
      headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/json'
      }
    });

    const data = await response.json();
    const items = data.threats || data.cases || [];
    allItems.push(...items);

    hasMore = data.nextPageNumber != null;
    pageNumber = data.nextPageNumber || pageNumber + 1;
  }

  return allItems;
}

OData Filtering

Abnormal Security supports OData-style filter expressions on list endpoints:

Filter Syntax

filter=<field> <operator> '<value>'

Supported Operators

| Operator | Description | Example | |----------|-------------|---------| | eq | Equals | attackType eq 'BEC' | | ne | Not equals | status ne 'Closed' | | gt | Greater than | riskScore gt 70 | | lt | Less than | riskScore lt 30 | | ge | Greater than or equal | sentTime ge '2026-03-01T00:00:00Z' | | le | Less than or equal | sentTime le '2026-03-27T00:00:00Z' | | and | Logical AND | attackType eq 'BEC' and severity eq 'Critical' | | or | Logical OR | attackType eq 'BEC' or attackType eq 'Phishing' |

Date Filtering

GET /v1/threats?filter=sentTime ge '2026-03-20T00:00:00Z' and sentTime le '2026-03-27T00:00:00Z'

Combined Filters

GET /v1/threats?filter=attackType eq 'BEC' and remediationStatus eq 'Not Remediated'&pageSize=50

Rate Limiting

Rate Limit Thresholds

| Limit Type | Value | Scope | |-----------|-------|-------| | Requests per minute | 60 | Per API token | | Requests per hour | 1,000 | Per API token |

Rate Limit Response

When rate limited, the API returns HTTP 429:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "error": "Rate limit exceeded. Please retry after 60 seconds."
}

Retry Strategy

async function requestWithRetry(url, options, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
      const jitter = Math.random() * 5000;
      await sleep(retryAfter * 1000 + jitter);
      continue;
    }

    if (response.status === 401) {
      throw new Error('Invalid API token. Regenerate at Settings > Integrations > API.');
    }

    return response;
  }

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

Error Handling

HTTP Status Codes

| Code | Meaning | Action | |------|---------|--------| | 200 | Success | Process response | | 400 | Bad Request | Check request format, filter syntax | | 401 | Unauthorized | Check API token | | 403 | Forbidden | Token lacks required permissions | | 404 | Not Found | Entity does not exist | | 429 | Rate Limited | Wait per Retry-After header | | 500 | Server Error | Retry with exponential backoff | | 503 | Service Unavailable | Temporary outage, retry later |

Error Response Format

{
  "error": "Invalid filter expression",
  "message": "The field 'attackType' does not support the operator 'contains'.",
  "statusCode": 400
}

Common Error Scenarios

| Error | Scenario | Resolution | |-------|----------|------------| | Invalid token | Token revoked or miscopied | Regenerate at Settings > Integrations > API | | Invalid filter | Unsupported OData expression | Check filter syntax and supported operators | | Entity not found | Threat/case ID does not exist | Verify the ID via list endpoint | | Permission denied | Token scope insufficient | Generate new token with required permissions | | Date range error | Dates in wrong format | Use ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ |

Performance Optimization

Minimize API Calls

// Good: Use filters to narrow results server-side
const threats = await client.threats.list({
  filter: "attackType eq 'BEC' and sentTime ge '2026-03-20T00:00:00Z'",
  pageSize: 100
});

// Avoid: Fetching all threats and filtering client-side
const allThreats = await client.threats.list({ pageSize: 100 });
const becThreats = allThreats.filter(t => t.attackType === 'BEC');

Parallelize Independent Requests

// Good: Independent endpoints in parallel
const [threats, cases, atoCases] = await Promise.all([
  client.threats.list({ pageSize: 25 }),
  client.cases.list({ pageSize: 2
Compartilhar X LinkedIn