Writing API Documentation That Screen Readers Love
A journalist's approach to creating accessible API documentation that actually helps developers build inclusive applications
Writing API Documentation That Screen Readers Love
How journalism training taught me to write API docs that work for everyone
The Problem Every API Team Faces
Your REST API passes all automated accessibility tests. Your frontend is WCAG 2.1 AA compliant. But when developers try to build accessible applications using your API, they struggle. Why?
Your API documentation isn’t accessible.
I discovered this the hard way while implementing Smart Accessibility Guardrails across multiple platforms. Teams would build beautifully accessible frontends, only to hit walls when they needed to understand error responses, authentication flows, or data structures that impact screen reader users.
The Journalism Approach to API Documentation
My journalism degree taught me that every piece of writing should answer: Who, What, When, Where, Why, and How. Applied to API documentation, this means:
Who: Define Your Audience’s Accessibility Needs
❌ Bad: "Returns user data" ✅ Good: "Returns user profile including
accessibility preferences for screen reader compatibility and high contrast
settings"
Why this matters: Developers need to know which fields affect assistive technology users.
What: Describe Accessibility Impact Clearly
// ❌ Unclear accessibility impact
{
"status": "error",
"code": 400,
"message": "Invalid input"
}
// ✅ Clear accessibility guidance
{
"status": "error",
"code": 400,
"message": "Email address format is invalid",
"accessibility": {
"announce": "Email validation error. Please check the email format.",
"focus_target": "email_input",
"severity": "error"
}
}
When: Timing Matters for Accessibility
Document when accessibility-related API calls should happen:
## Authentication Flow for Assistive Technology
1. **Before page load**: Call `/api/user/preferences` to get accessibility
settings
2. **During login**: Include `accessibility_preferences: true` in request
3. **After successful auth**: Cache accessibility settings for offline use
4. **On settings change**: Immediately call `/api/user/accessibility` to update
Where: Location Context for Inclusive Design
# OpenAPI specification with accessibility context
paths:
/api/announcements:
get:
summary: 'Get system announcements for screen readers'
description: |
Retrieves announcements that should be immediately communicated
to screen reader users. Announcements marked as 'urgent' should
trigger assertive ARIA live regions.
parameters:
- name: priority
in: query
description: 'Filter by announcement priority for ARIA live regions'
schema:
type: string
enum: ['polite', 'assertive', 'off']
Why: Explain Accessibility Decisions
Don’t just document what the API does—explain why it matters for accessibility:
## Error Response Format
Our error responses follow this structure to support screen readers:
```json
{
"error": {
"code": "VALIDATION_FAILED",
"message": "The email field contains an invalid email address",
"field": "email",
"user_message": "Please enter a valid email address like user@example.com"
}
}
```
Why this structure?
message: Technical description for developersuser_message: Screen reader-friendly text for end usersfield: Enables programmatic focus management
### How: Provide Working Examples
Every accessibility feature needs a complete, testable example:
```javascript
// Example: Implementing accessible form validation with our API
async function validateAccessibly(formData) {
try {
const response = await fetch('/api/validate', {
method: 'POST',
body: JSON.stringify(formData),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
const result = await response.json();
if (!response.ok) {
// Focus management for screen readers
if (result.error?.field) {
const errorField = document.getElementById(result.error.field);
if (errorField) {
errorField.focus();
errorField.setAttribute('aria-invalid', 'true');
}
}
// Announce error to screen readers
if (result.accessibility?.announce) {
announceToScreenReader(result.accessibility.announce);
} else if (result.error?.message) {
announceToScreenReader(result.error.message);
}
}
return result;
} catch (error) {
announceToScreenReader('A network error occurred. Please try again.');
throw error;
}
}
function announceToScreenReader(message) {
const announcement = document.createElement('div');
announcement.setAttribute('aria-live', 'assertive');
announcement.setAttribute('aria-atomic', 'true');
announcement.textContent = message;
announcement.style.position = 'absolute';
announcement.style.left = '-10000px';
document.body.appendChild(announcement);
setTimeout(() => {
if (document.body.contains(announcement)) {
document.body.removeChild(announcement);
}
}, 1000);
}
The Smart Accessibility Guardrails Approach to API Docs
Here’s how I integrate accessibility documentation into API development:
1. Accessibility-First OpenAPI Specifications
components:
schemas:
StandardError:
type: object
required: [code, message]
properties:
code:
type: string
description: 'Machine-readable error code'
message:
type: string
description: 'Human-readable error description'
field:
type: string
description:
'Field name that caused the error (for validation errors)'
AccessibleErrorResponse:
type: object
required: [error, accessibility]
properties:
error:
$ref: '#/components/schemas/StandardError'
accessibility:
type: object
properties:
announce:
type: string
description: 'Screen reader announcement text'
severity:
type: string
enum: ['info', 'warning', 'error']
description: 'ARIA live region priority'
focus_target:
type: string
description: 'Element ID to focus after error'
2. Automated Accessibility Documentation Testing
// Test that ensures API docs include accessibility guidance
describe('API Documentation Accessibility', () => {
test('all error responses include accessibility fields', async () => {
// Load your OpenAPI specification
const fs = require('fs');
const yaml = require('js-yaml');
const apiSpec = yaml.load(fs.readFileSync('./api-spec.yaml', 'utf8'));
Object.values(apiSpec.paths).forEach(pathSpec => {
Object.values(pathSpec).forEach(operation => {
const errorResponses = Object.keys(operation.responses).filter(
code => code.startsWith('4') || code.startsWith('5')
);
errorResponses.forEach(errorCode => {
const response = operation.responses[errorCode];
const schema = response.content?.['application/json']?.schema;
// Check if error responses include accessibility guidance
expect(schema?.properties).toHaveProperty('accessibility');
});
});
});
});
});
3. Living Documentation with Real Examples
Create documentation that stays current:
## Real Implementation Examples
### Video Streaming API Integration
Here's how to implement screen reader announcements for video playback status:
```javascript
// Video status updates with accessibility support
const updateVideoStatus = async (videoId, status) => {
try {
const response = await fetch(`/api/videos/${videoId}/status`, {
method: 'PATCH',
body: JSON.stringify({ status }),
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});
const result = await response.json();
// Use API-provided accessibility text if available
if (result.accessibility?.announce) {
announceToScreenReader(result.accessibility.announce);
} else {
// Fallback to generating announcement from status
const statusMessages = {
playing: 'Video is now playing',
paused: 'Video is paused',
stopped: 'Video has stopped',
ended: 'Video has ended',
};
announceToScreenReader(
statusMessages[status] || `Video status: ${status}`
);
}
return result;
} catch (error) {
announceToScreenReader('Unable to update video status');
throw error;
}
};
```
📋 Implementation Status: Example code pattern - adapt to your specific API 🔧 Screen Reader Testing: Recommended with NVDA (free), JAWS, or VoiceOver (built into Mac) � Documentation: Include accessibility guidance in your OpenAPI specs
## The Business Case for Accessible API Documentation
From my research on accessibility implementation across development teams:
- **Increased awareness** of accessibility best practices among developers
- **Faster integration** times for teams building accessible applications
- **Higher developer satisfaction** with clear, actionable documentation
- **Legal compliance** for APIs used in government or educational applications
## Action Items for Your API Team
1. **Audit your current API docs** for accessibility guidance
2. **Add accessibility fields** to error response schemas
3. **Include screen reader examples** in all integration guides
4. **Test with screen readers**: Start with VoiceOver (Mac users) or NVDA (free for Windows)
5. **Automate accessibility doc validation** in your CI/CD pipeline
## Getting Started with Screen Reader Testing
**For Mac users**: VoiceOver is already installed! Press `Cmd + F5` to turn it on and test your documentation.
**For Windows users**: Download [NVDA](https://www.nvaccess.org/) (free) to test how screen readers interact with your API documentation.
**Testing tip**: Navigate your API docs using only the keyboard and screen reader. If it's confusing for you, it will be confusing for users with visual impairments.
## What's Next?
This is part of my larger "Smart Accessibility Guardrails" methodology that I'm applying across cloud infrastructure, mobile applications, and DevOps pipelines. Next week, I'll share how to implement accessibility testing in Azure DevOps pipelines.
**Questions?** I'd love to hear how you're making your API documentation more accessible. Connect with me on [LinkedIn](https://linkedin.com/in/rubyjane/) or share your experiences in the comments.
---
*Ruby Jane Cabagnot is a Cloud Accessibility Engineer, author of "Practical Enterprise React," and international speaker who combines journalism training with technical expertise to create accessible, understandable documentation. She's currently pursuing a Master's in Cloud Engineering at OsloMet.*