home / skills / secondsky / claude-skills / api-filtering-sorting

This skill helps you implement flexible API filtering and sorting by parsing query parameters, validating input, and securing endpoints.

npx playbooks add skill secondsky/claude-skills --skill api-filtering-sorting

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.3 KB
---
name: api-filtering-sorting
description: Builds flexible API filtering and sorting systems with query parameter parsing, validation, and security. Use when implementing search endpoints, building data grids, or creating dynamic query APIs.
---

# API Filtering & Sorting

Build flexible filtering and sorting systems that handle complex queries efficiently.

## Query Parameter Syntax

```
GET /products?category=electronics&price[gte]=100&price[lte]=500&sort=-price,name
```

## Implementation (Node.js)

```javascript
const allowedFilters = ['category', 'status', 'price', 'createdAt'];
const allowedSorts = ['name', 'price', 'createdAt'];

app.get('/products', async (req, res) => {
  const filter = {};
  const sort = {};

  // Parse filters
  for (const [key, value] of Object.entries(req.query)) {
    if (key === 'sort') continue;

    const match = key.match(/^(\w+)\[(\w+)\]$/);
    if (match) {
      const [, field, operator] = match;
      if (!allowedFilters.includes(field)) continue;
      filter[field] = { [`$${operator}`]: parseValue(value) };
    } else if (allowedFilters.includes(key)) {
      filter[key] = value;
    }
  }

  // Parse sort
  if (req.query.sort) {
    for (const field of req.query.sort.split(',')) {
      const direction = field.startsWith('-') ? -1 : 1;
      const name = field.replace(/^-/, '');
      if (allowedSorts.includes(name)) sort[name] = direction;
    }
  }

  const products = await Product.find(filter).sort(sort);
  res.json({ data: products });
});

function parseValue(value) {
  if (value === 'true') return true;
  if (value === 'false') return false;
  if (!isNaN(value)) return Number(value);
  return value;
}
```

## Filter Operators

| Operator | Meaning | Example |
|----------|---------|---------|
| eq | Equals | `?status=active` |
| ne | Not equals | `?status[ne]=deleted` |
| gt/gte | Greater than | `?price[gte]=100` |
| lt/lte | Less than | `?price[lte]=500` |
| in | In array | `?status[in]=active,pending` |
| like | Contains | `?name[like]=phone` |

## Security

- Whitelist allowed filter fields
- Validate input types per field
- Index frequently-filtered columns
- Limit query complexity
- Prevent SQL/NoSQL injection

## Best Practices

- Support common operators
- Cache filter option lists
- Monitor query performance
- Provide sensible defaults

Overview

This skill builds flexible API filtering and sorting systems with robust query parameter parsing, validation, and security safeguards. It provides a production-oriented approach for search endpoints, data grids, and dynamic query APIs using TypeScript and Node.js patterns. The implementation focuses on whitelisting, operator support, and safe value parsing to avoid injection and performance issues.

How this skill works

The skill parses query parameters into filter and sort objects, supporting operators like eq, ne, gt/gte, lt/lte, in, and like. It enforces allowed filter and sort lists, converts string values to proper types (boolean, number, string), and maps operator syntax (e.g., price[gte]) into driver-friendly query clauses. It also recommends indexing, input validation, and query complexity limits to protect runtime performance and security.

When to use it

  • Implementing REST search endpoints that need flexible client-driven filters.
  • Building data grids or admin UIs with multi-field sorting and filter controls.
  • Creating public APIs that accept dynamic queries without exposing database internals.
  • Replacing ad-hoc query parsing with a consistent, auditable filtering layer.
  • Optimizing common query patterns for performance and index usage.

Best practices

  • Whitelist allowed filter and sort fields rather than trusting all query keys.
  • Validate each field’s expected type and range before composing the query.
  • Support a small, well-defined set of operators: eq, ne, gt/gte, lt/lte, in, like.
  • Parse values to booleans and numbers centrally to avoid type confusion.
  • Limit pagination and query complexity; enforce timeouts and max clauses.
  • Index frequently filtered/sorted columns and monitor query performance.

Example use cases

  • Products endpoint: filter by category, price range, availability, and sort by price or name.
  • Admin dashboard: combine status[in]=active,pending with createdAt[gte] to review recent records.
  • Reporting API: allow clients to request aggregated lists with safe, server-controlled filters.
  • Search-powered UI: implement server-side like=name[like] plus multi-column sort for fast UX.
  • Rate-limited public API: accept limited dynamic queries while preventing expensive full-table scans.

FAQ

How do you prevent injection attacks?

Whitelist fields, validate types and operators, and never concatenate raw strings into SQL/NoSQL queries; use parameterized queries or the database driver's query builder.

What operators should I support first?

Start with eq, ne, gt/gte, lt/lte, in, and like — they cover common needs without adding unnecessary complexity.

How should I handle arrays for the in operator?

Accept comma-separated values and parse them into typed arrays, validating element types against the field schema.