# Send API Security Best Practices to your agent
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
## Fast path
- Download the package from Yavira.
- Extract it into a folder your agent can access.
- Paste one of the prompts below and point your agent at the extracted folder.
## Suggested prompts
### New install

```text
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
```
### Upgrade existing

```text
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
```
## Machine-readable fields
```json
{
  "schemaVersion": "1.0",
  "item": {
    "slug": "api-security",
    "name": "API Security Best Practices",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/brandonwise/api-security",
    "canonicalUrl": "https://clawhub.ai/brandonwise/api-security",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadUrl": "/downloads/api-security",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=api-security",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "packageFormat": "ZIP package",
    "primaryDoc": "SKILL.md",
    "includedAssets": [
      "SKILL.md"
    ],
    "downloadMode": "redirect",
    "sourceHealth": {
      "source": "tencent",
      "slug": "api-security",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-29T07:25:13.375Z",
      "expiresAt": "2026-05-06T07:25:13.375Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=api-security",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=api-security",
        "contentDisposition": "attachment; filename=\"api-security-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null,
        "slug": "api-security"
      },
      "scope": "item",
      "summary": "Item download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this item.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/api-security"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    }
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/api-security",
    "downloadUrl": "https://openagent3.xyz/downloads/api-security",
    "agentUrl": "https://openagent3.xyz/skills/api-security/agent",
    "manifestUrl": "https://openagent3.xyz/skills/api-security/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/api-security/agent.md"
  }
}
```
## Documentation

### API Security Best Practices

Implement secure API design patterns including authentication, authorization, input validation, rate limiting, and protection against common API vulnerabilities.

### Description

USE WHEN:

Designing new API endpoints
Securing existing APIs
Implementing authentication and authorization (JWT, OAuth 2.0, API keys)
Setting up rate limiting and throttling
Protecting against injection attacks (SQL, XSS, command)
Conducting API security reviews or preparing for audits
Handling sensitive data in APIs
Building REST, GraphQL, or WebSocket APIs

DON'T USE WHEN:

Need vulnerability scanning (use vulnerability-scanner skill)
Building frontend-only apps with no API
Need network-level security (firewalls, WAF config)

OUTPUTS:

Secure authentication implementations (JWT, refresh tokens)
Input validation schemas (Zod, Joi)
Rate limiting configurations
Security middleware examples
OWASP API Top 10 compliance guidance

### Step 1: Authentication & Authorization

Choose authentication method (JWT, OAuth 2.0, API keys)
Implement token-based authentication
Set up role-based access control (RBAC)
Secure session management
Implement multi-factor authentication (MFA)

### Step 2: Input Validation & Sanitization

Validate all input data
Sanitize user inputs
Use parameterized queries
Implement request schema validation
Prevent SQL injection, XSS, and command injection

### Step 3: Rate Limiting & Throttling

Implement rate limiting per user/IP
Set up API throttling
Configure request quotas
Handle rate limit errors gracefully
Monitor for suspicious activity

### Step 4: Data Protection

Encrypt data in transit (HTTPS/TLS)
Encrypt sensitive data at rest
Implement proper error handling (no data leaks)
Sanitize error messages
Use secure headers

### Generate Secure JWT Tokens

// auth.js
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');

app.post('/api/auth/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    
    // Validate input
    if (!email || !password) {
      return res.status(400).json({ error: 'Email and password required' });
    }
    
    // Find user
    const user = await db.user.findUnique({ where: { email } });
    
    if (!user) {
      // Don't reveal if user exists
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    // Verify password
    const validPassword = await bcrypt.compare(password, user.passwordHash);
    if (!validPassword) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    // Generate JWT token
    const token = jwt.sign(
      { userId: user.id, email: user.email, role: user.role },
      process.env.JWT_SECRET,
      { expiresIn: '1h', issuer: 'your-app', audience: 'your-app-users' }
    );
    
    // Generate refresh token
    const refreshToken = jwt.sign(
      { userId: user.id },
      process.env.JWT_REFRESH_SECRET,
      { expiresIn: '7d' }
    );
    
    // Store refresh token in database
    await db.refreshToken.create({
      data: {
        token: refreshToken,
        userId: user.id,
        expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
      }
    });
    
    res.json({ token, refreshToken, expiresIn: 3600 });
  } catch (error) {
    console.error('Login error:', error);
    res.status(500).json({ error: 'An error occurred during login' });
  }
});

### JWT Verification Middleware

// middleware/auth.js
const jwt = require('jsonwebtoken');

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
  
  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }
  
  jwt.verify(
    token, 
    process.env.JWT_SECRET,
    { issuer: 'your-app', audience: 'your-app-users' },
    (err, user) => {
      if (err) {
        if (err.name === 'TokenExpiredError') {
          return res.status(401).json({ error: 'Token expired' });
        }
        return res.status(403).json({ error: 'Invalid token' });
      }
      req.user = user;
      next();
    }
  );
}

module.exports = { authenticateToken };

### ❌ Vulnerable Code

// NEVER DO THIS - SQL Injection vulnerability
app.get('/api/users/:id', async (req, res) => {
  const userId = req.params.id;
  const query = \`SELECT * FROM users WHERE id = '${userId}'\`;
  const user = await db.query(query);
  res.json(user);
});

// Attack: GET /api/users/1' OR '1'='1 → Returns all users!

### ✅ Safe: Parameterized Queries

app.get('/api/users/:id', async (req, res) => {
  const userId = req.params.id;
  
  // Validate input first
  if (!userId || !/^\\d+$/.test(userId)) {
    return res.status(400).json({ error: 'Invalid user ID' });
  }
  
  // Use parameterized query
  const user = await db.query(
    'SELECT id, email, name FROM users WHERE id = $1',
    [userId]
  );
  
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  
  res.json(user);
});

### ✅ Safe: Using ORM (Prisma)

app.get('/api/users/:id', async (req, res) => {
  const userId = parseInt(req.params.id);
  
  if (isNaN(userId)) {
    return res.status(400).json({ error: 'Invalid user ID' });
  }
  
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: { id: true, email: true, name: true } // Don't select sensitive fields
  });
  
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  
  res.json(user);
});

### Schema Validation with Zod

const { z } = require('zod');

const createUserSchema = z.object({
  email: z.string().email('Invalid email format'),
  password: z.string()
    .min(8, 'Password must be at least 8 characters')
    .regex(/[A-Z]/, 'Must contain uppercase letter')
    .regex(/[a-z]/, 'Must contain lowercase letter')
    .regex(/[0-9]/, 'Must contain number'),
  name: z.string().min(2).max(100),
  age: z.number().int().min(18).max(120).optional()
});

function validateRequest(schema) {
  return (req, res, next) => {
    try {
      schema.parse(req.body);
      next();
    } catch (error) {
      res.status(400).json({ error: 'Validation failed', details: error.errors });
    }
  };
}

app.post('/api/users', validateRequest(createUserSchema), async (req, res) => {
  // Input is validated at this point
  const { email, password, name, age } = req.body;
  const passwordHash = await bcrypt.hash(password, 10);
  const user = await prisma.user.create({ data: { email, passwordHash, name, age } });
  const { passwordHash: _, ...userWithoutPassword } = user;
  res.status(201).json(userWithoutPassword);
});

### Rate Limiting

const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');

const redis = new Redis({
  host: process.env.REDIS_HOST,
  port: process.env.REDIS_PORT
});

// General API rate limit
const apiLimiter = rateLimit({
  store: new RedisStore({ client: redis, prefix: 'rl:api:' }),
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  message: { error: 'Too many requests, please try again later', retryAfter: 900 },
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: (req) => req.user?.userId || req.ip
});

// Strict rate limit for authentication
const authLimiter = rateLimit({
  store: new RedisStore({ client: redis, prefix: 'rl:auth:' }),
  windowMs: 15 * 60 * 1000,
  max: 5, // Only 5 login attempts per 15 minutes
  skipSuccessfulRequests: true,
  message: { error: 'Too many login attempts, please try again later', retryAfter: 900 }
});

app.use('/api/', apiLimiter);
app.use('/api/auth/login', authLimiter);
app.use('/api/auth/register', authLimiter);

### Security Headers (Helmet)

const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      scriptSrc: ["'self'"],
      imgSrc: ["'self'", 'data:', 'https:']
    }
  },
  frameguard: { action: 'deny' },
  hidePoweredBy: true,
  noSniff: true,
  hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }
}));

### ❌ Bad: Only Authentication

app.delete('/api/posts/:id', authenticateToken, async (req, res) => {
  await prisma.post.delete({ where: { id: req.params.id } });
  res.json({ success: true });
});

### ✅ Good: Authentication + Authorization

app.delete('/api/posts/:id', authenticateToken, async (req, res) => {
  const post = await prisma.post.findUnique({ where: { id: req.params.id } });
  
  if (!post) {
    return res.status(404).json({ error: 'Post not found' });
  }
  
  // Check if user owns the post or is admin
  if (post.userId !== req.user.userId && req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Not authorized to delete this post' });
  }
  
  await prisma.post.delete({ where: { id: req.params.id } });
  res.json({ success: true });
});

### ✅ Do This

Use HTTPS Everywhere - Never send sensitive data over HTTP
Implement Authentication - Require authentication for protected endpoints
Validate All Inputs - Never trust user input
Use Parameterized Queries - Prevent SQL injection
Implement Rate Limiting - Protect against brute force and DDoS
Hash Passwords - Use bcrypt with salt rounds >= 10
Use Short-Lived Tokens - JWT access tokens should expire quickly
Implement CORS Properly - Only allow trusted origins
Log Security Events - Monitor for suspicious activity
Use Security Headers - Implement Helmet.js
Sanitize Error Messages - Don't leak sensitive information

### ❌ Don't Do This

Don't Store Passwords in Plain Text
Don't Use Weak Secrets - Use strong, random JWT secrets
Don't Trust User Input - Always validate and sanitize
Don't Expose Stack Traces - Hide error details in production
Don't Use String Concatenation for SQL
Don't Store Sensitive Data in JWT - JWTs are not encrypted
Don't Ignore Security Updates - Update dependencies regularly
Don't Log Sensitive Data

### OWASP API Security Top 10

Broken Object Level Authorization - Always verify user can access resource
Broken Authentication - Implement strong authentication mechanisms
Broken Object Property Level Authorization - Validate which properties user can access
Unrestricted Resource Consumption - Implement rate limiting and quotas
Broken Function Level Authorization - Verify user role for each function
Unrestricted Access to Sensitive Business Flows - Protect critical workflows
Server Side Request Forgery (SSRF) - Validate and sanitize URLs
Security Misconfiguration - Use security best practices and headers
Improper Inventory Management - Document and secure all API endpoints
Unsafe Consumption of APIs - Validate data from third-party APIs

### Authentication & Authorization

Implement strong authentication (JWT, OAuth 2.0)
 Use HTTPS for all endpoints
 Hash passwords with bcrypt (salt rounds >= 10)
 Implement token expiration
 Add refresh token mechanism
 Verify user authorization for each request
 Implement role-based access control (RBAC)

### Input Validation

Validate all user inputs
 Use parameterized queries or ORM
 Sanitize HTML content
 Validate file uploads
 Implement request schema validation
 Use allowlists, not blocklists

### Rate Limiting & DDoS Protection

Implement rate limiting per user/IP
 Add stricter limits for auth endpoints
 Use Redis for distributed rate limiting
 Return proper rate limit headers
 Implement request throttling

### Data Protection

Use HTTPS/TLS for all traffic
 Encrypt sensitive data at rest
 Don't store sensitive data in JWT
 Sanitize error messages
 Implement proper CORS configuration
 Use security headers (Helmet.js)

### Additional Resources

OWASP API Security Top 10
JWT Best Practices
Express Security Best Practices
API Security Checklist
## Trust
- Source: tencent
- Verification: Indexed source record
- Publisher: brandonwise
- Version: 1.0.0
## Source health
- Status: healthy
- Item download looks usable.
- Yavira can redirect you to the upstream package for this item.
- Health scope: item
- Reason: direct_download_ok
- Checked at: 2026-04-29T07:25:13.375Z
- Expires at: 2026-05-06T07:25:13.375Z
- Recommended action: Download for OpenClaw
## Links
- [Detail page](https://openagent3.xyz/skills/api-security)
- [Send to Agent page](https://openagent3.xyz/skills/api-security/agent)
- [JSON manifest](https://openagent3.xyz/skills/api-security/agent.json)
- [Markdown brief](https://openagent3.xyz/skills/api-security/agent.md)
- [Download page](https://openagent3.xyz/downloads/api-security)