How to optimize your API documentation so Cursor's code intelligence retrieves your examples as references
Photo: Unsplash
When Cursor's code intelligence scans your API documentation, it extracts examples and patterns to suggest them during development. The difference between documentation that gets surfaced and documentation that gets ignored comes down to structure, naming clarity, and how you format code examples. Well-optimized docs appear in Cursor's suggestions because the AI can parse them reliably and match them to the developer's context.
What format makes your API examples machine-readable to Cursor?
Cursor's retrieval system works best with examples stored as standalone, properly-labeled code blocks rather than prose-embedded snippets. Use fenced code blocks with explicit language identifiers (```javascript not ```). Include a comment header in each example that describes what it demonstrates, written in plain language: // Fetch user profile with error handling works better than // Example 1.
Structure your code examples so they're copy-paste ready. Remove placeholder comments that need user interpretation. If a param is optional, show that in the code with a clear default or conditional, not in a separate note below the block. Cursor indexes examples that look like they could run immediately, not tutorials that require assembly.
Store related examples in a predictable location. If your endpoint is /users/{id}, nest all its examples under a consistent heading structure. Cursor's context window can pull from nearby sections. Scattered examples across separate pages dilute the signal.
How should you name variables and parameters for better AI matching?
Use full, descriptive names in your examples instead of shortened versions. Write userId and userName, not uid or u. Cursor matches against the code your developer is writing right now. When they type userId, the AI should find examples using that exact term.
Name your example variables after what they represent in the real world. const user = response.data signals intent better than const x = r.d. Single-letter variables were never great for humans; they're worse for retrieval systems that learn patterns from variable semantics.
Consistency in naming across examples matters more than you might think. If one example calls a user object user and another calls it userData, Cursor sees two separate patterns instead of one unified concept. Pick a naming convention, document it, and stick to it across all code samples.
What metadata should you add to make examples discoverable?
Include a structured comment at the top of each example block that answers: what is this for, when would you use it, and what does it return. Here's the pattern:
// USE: Retrieve user by ID with role information
// RETURNS: User object with nested roles array
// ERROR HANDLING: Throws 404 if user not found
This metadata helps Cursor match examples to context without having to parse the entire implementation. When a developer is in error-handling mode, that third line becomes the hook that surfaces your example.
Add tags or keywords in documentation heading structures. Instead of "Example: Getting a User", use "Example: Get User By ID (with error handling, role filtering)". Cursor scans headings and nearby text to understand what category of problem each example solves.
If you maintain API docs in a tool like Swagger/OpenAPI, populate the description and x-example fields with complete, working code blocks. Don't leave them empty or use placeholder text. kotopost can help you track whether your example visibility is improving across different AI assistants over time.
Should your examples demonstrate happy paths only, or include error cases?
Examples that show only the success case get retrieved less often than examples that demonstrate real-world failure handling. Cursor is trained on production code, and production code handles errors.
Include at least one example per major endpoint that shows error handling. Demonstrate the 404, 401, or 400 response and how a developer should respond to it. Use a try-catch block or a .catch() handler, depending on your language.
// USE: Create a new user account
// RETURNS: New user object with ID
// ERRORS: 400 (validation), 409 (email exists)
async function createUser(email, name) {
try {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, name })
});
if (!response.ok) {
if (response.status === 409) {
throw new Error('Email already exists');
}
throw new Error(`Server error: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('User creation failed:', error.message);
throw error;
}
}
This example teaches two things at once: the happy path and what to do when email validation fails. Cursor pulls it when a developer nearby is thinking about error handling.
How do you structure docs so Cursor's context window captures complete examples?
Cursor operates with a fixed context window. Long examples that span hundreds of lines won't fully load. Break large workflows into smaller, focused examples instead of one monolithic 200-line script.
If you need to show a complex workflow, provide it as three separate examples: "Initialize client", "Authenticate", "Fetch data". Stack them in order on the page. Cursor can then pull the first two when context space is tight and still suggest a relevant pattern.
Use sub-headings to separate distinct use cases. "Create user" and "Bulk create users" should be separate examples with separate headings, not variations within one example. This helps Cursor segment its retrieval: if a developer is writing a loop, the "bulk" example becomes relevant; if they're handling a single form submission, the "create user" example is the match.
Keep examples to 15-30 lines where possible. This is the sweet spot for fitting into Cursor's context and remaining useful without overwhelming the developer with complexity.
What documentation structure helps Cursor understand parameter relationships?
Document parameters as a structured list, not as inline prose. Use a table or nested list that shows parameter name, type, required/optional status, and what values it accepts.
### Parameters
| Name | Type | Required | Description |
|------|------|----------|-------------|
| userId | string | Yes | Unique user identifier |
| include | string | No | Comma-separated fields: roles, settings, profile |
| limit | integer | No | Max results (1-100, default 20) |
Below the table, add one complete example that uses several of these parameters together:
// Show how multiple parameters work together in practice
const users = await client.users.list({
userId: 'user_123',
include: 'roles,settings',
limit: 50
});
When Cursor sees a developer working with the include parameter, it can connect that back to your table, then suggest the example that demonstrates how include actually gets used. The table is the schema; the example is the proof.
Should you version your examples when your API changes?
Yes, and mark old examples clearly. If your API has major versions (v1 and v2), maintain separate example sections. Use headings like "Create user (v2, current)" and "Create user (v1, deprecated)".
For small breaking changes within a version, add an inline note above the example:
// NOTE: As of 2024-Q2, the 'metadata' field returns nested objects.
// Previous versions returned flat strings.
This prevents Cursor from suggesting outdated patterns. A developer using the latest SDK should not receive suggestions for v1 syntax.
Include a migration example when you deprecate an endpoint. Show the old pattern and the new one side by side (or sequentially) with clear labels. Cursor can then help developers move to the new API faster.