Crash Courses · Masters
Consuming APIs with fetch
Fetch, cache, and handle errors from external REST APIs in Next.js.
10 min read+175 XP on completionCert: REST APIs Crash Course
Tap any word in the text below to start reading from there.
Consuming APIs with fetch
fetch is the universal HTTP client. Typed wrappers give you consistency and type safety across all API calls.
Basic Fetch
// fetch rejects only on network error — always check res.ok
const res = await fetch('/api/courses')
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`)
}
const data = await res.json()Typed API Client
// lib/api.ts
type ApiResponse<T> = { data: T; error?: never } | { data?: never; error: string }
async function apiFetch<T>(
url: string,
options?: RequestInit
): Promise<ApiResponse<T>> {
try {
const res = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
})
const json = await res.json()
if (!res.ok) {
return { error: json.error ?? `HTTP ${res.status}` }
}
return { data: json.data ?? json }
} catch (err) {
return { error: 'Network error' }
}
}
// Usage — fully typed
const { data: courses, error } = await apiFetch<Course[]>('/api/courses')
if (error) return <Error message={error} />
return <CourseList courses={courses} />Fetch with Timeout
async function fetchWithTimeout<T>(url: string, ms = 5000): Promise<T> {
const controller = new AbortController()
const id = setTimeout(() => controller.abort(), ms)
try {
const res = await fetch(url, { signal: controller.signal })
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json()
} finally {
clearTimeout(id)
}
}Azure TTS API Call Pattern (used in this app)
const speechRes = await fetch(
`https://${region}.tts.speech.microsoft.com/cognitiveservices/v1`,
{
method: 'POST',
headers: {
'Ocp-Apim-Subscription-Key': process.env.AZURE_SPEECH_KEY!,
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': 'audio-48khz-192kbitrate-mono-mp3',
},
body: ssmlString,
}
)
if (!speechRes.ok) {
throw new Error(`Azure TTS error: ${speechRes.status}`)
}
const audioBuffer = await speechRes.arrayBuffer()Reading progress
0% read
In this module
fetch API
Error handling
Typed fetch wrapper
AbortController
0%