CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/api-design-patterns

REST API design patterns — response envelopes, pagination, filtering, status codes, and resource naming

87

1.78x
Quality

83%

Does it follow best practices?

Impact

98%

1.78x

Average score across 4 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "Tests whether the agent applies REST API design patterns when building a product catalog: response envelopes, pagination for a 50k-product dataset, correct status codes, proper resource naming, PATCH semantics for partial updates, and filtering.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "success-response-envelope",
      "description": "Success responses wrap the resource or resource array in a { data: ... } envelope",
      "max_score": 10
    },
    {
      "name": "error-response-envelope",
      "description": "Error responses use a consistent { error: { code: '...', message: '...' } } structure",
      "max_score": 10
    },
    {
      "name": "list-endpoint-paginated",
      "description": "The GET /products list endpoint supports pagination via query parameters (cursor/limit or page/limit) rather than returning all 50,000 products",
      "max_score": 12
    },
    {
      "name": "pagination-metadata",
      "description": "Paginated responses include pagination metadata (next_cursor/has_more, or page/total/total_pages) alongside the data array",
      "max_score": 8
    },
    {
      "name": "default-and-max-limit",
      "description": "Pagination has a default limit and a maximum limit that clamps client-provided values",
      "max_score": 6
    },
    {
      "name": "filtering-support",
      "description": "The list endpoint supports filtering by at least category and price range via query parameters",
      "max_score": 8
    },
    {
      "name": "201-for-post",
      "description": "The POST endpoint returns 201 Created on successful product creation, not 200",
      "max_score": 8
    },
    {
      "name": "204-for-delete",
      "description": "The DELETE endpoint returns 204 No Content on successful deletion",
      "max_score": 6
    },
    {
      "name": "404-for-not-found",
      "description": "GET, PATCH, and DELETE for a non-existent product ID return 404 Not Found",
      "max_score": 6
    },
    {
      "name": "plural-noun-resource-path",
      "description": "Resource URLs use plural nouns (e.g., /products, /api/products) with no verbs in the path",
      "max_score": 6
    },
    {
      "name": "patch-partial-update",
      "description": "The update endpoint uses PATCH and only modifies fields present in the request body — fields not sent are left unchanged",
      "max_score": 10
    },
    {
      "name": "patch-returns-full-resource",
      "description": "The PATCH endpoint returns the full updated product in the response",
      "max_score": 5
    },
    {
      "name": "validation-error-status",
      "description": "Validation errors (e.g., missing required fields on create) return 422 or 400 with an error envelope",
      "max_score": 5
    }
  ]
}

evals

tile.json