Dev.to’s API supports both unauthenticated and authenticated access, letting you fetch public articles or access private drafts, analytics, and more—all easily integrated into your Next.js portfolio.
🔓 1. Public Endpoints (No API Key Required)
Fetch any user's public posts with a simple GET request:
const articles = await fetch(`https://dev.to/api/articles?username=${username}`)
.then(res => res.json());
console.log(articles);
Example Response:
https://dev.to/api/articles?username=dariomannu&page=1&per_page=5
[
{
"type_of": "article",
"id": 2691219,
"title": "Callforwards are actually not that bad!",
"description": "Have you ever tried callforwards? If you've used Express.js before, it's the same concept, but for...",
"readable_publish_date": "Jul 19",
"slug": "callforwards-are-actually-not-that-bad-475e",
"path": "/dariomannu/callforwards-are-actually-not-that-bad-475e",
"url": "https://dev.to/dariomannu/callforwards-are-actually-not-that-bad-475e",
"comments_count": 0,
"public_reactions_count": 4,
"collection_id": null,
"published_timestamp": "2025-07-19T09:00:00Z",
"language": "en",
"subforem_id": 1,
"positive_reactions_count": 4,
"cover_image": "https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h9k3bw7gtbtli24qtt3.png",
"social_image": "https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2h9k3bw7gtbtli24qtt3.png",
"canonical_url": "https://dev.to/dariomannu/callforwards-are-actually-not-that-bad-475e",
"created_at": "2025-07-15T17:51:58Z",
"edited_at": "2025-07-19T07:25:14Z",
"crossposted_at": null,
"published_at": "2025-07-19T09:00:00Z",
"last_comment_at": "2025-07-19T09:00:00Z",
"reading_time_minutes": 2,
"tag_list": [
"javascript",
"frontend",
"webdev",
"express"
],
"tags": "javascript, frontend, webdev, express",
"user": {
"name": "Dario Mannu",
"username": "dariomannu",
"twitter_username": null,
"github_username": "dariomannu",
"user_id": 1100953,
"website_url": "https://github.com/reactivehtml",
"profile_image": "https://media2.dev.to/dynamic/image/width=640,height=640,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1100953%2F8136174b-bd57-4769-8a35-28a970127779.png",
"profile_image_90": "https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1100953%2F8136174b-bd57-4769-8a35-28a970127779.png"
}
},
]
You can:
- Get by ID:
const article = await fetch(`https://dev.to/api/articles/${articleId}`)
.then(res => res.json());
- Get by slug:
const article = await fetch(`https://dev.to/api/articles/${username}/${slug}`)
.then(res => res.json());
- Get user info:
const user = await fetch(`https://dev.to/api/users/${userId}`)
.then(res => res.json());
const userByName = await fetch(`https://dev.to/api/users/by_username?url=${username}`)
.then(res => res.json());
🔐 2. Authenticated Endpoints (API Key Required)
Enable access to private drafts, analytics, followers, and more. Use only in server-side or API route — CORS disabled.
// Example server-side fetch
const articles = await fetch('https://dev.to/api/articles/me', {
headers: { 'api-key': process.env.DEV_TO_API_KEY }
}).then(res => res.json());
Available endpoints:
-
GET /api/articles/me
– All your articles (drafts + published) GET /api/articles/me/published
GET /api/articles/me/unpublished
GET /api/articles/me/all
-
GET /api/users/me
(your profile data)
🗂️ Feature Comparison Table
Feature | Public (No Key) | Authenticated (With Key) |
---|---|---|
Authentication | ❌ None | ✅ api-key header |
Access Scope | Public posts only | Your drafts, analytics, followers, etc. |
Browser-Friendly | ✅ Yes | ❌ No—server/API routes only |
CORS Support | ✅ Yes | ❌ No |
Endpoints |
/articles , /articles/:id , etc. |
/me , /me/published , /me/unpublished , etc. |
🔧 How to Use in Next.js
a. Fetch Public Posts (SSG/ISR)
// app/page.tsx (Next.js)
export default async function HomePage() {
const posts = await fetch(
'https://dev.to/api/articles?username=yourname&per_page=5'
).then(res => res.json());
return (
<main>
<h1>Public Posts</h1>
<ul>
{posts.map(p => (
<li key={p.id}>
<a href={p.url} target="_blank" rel="noreferrer">
{p.title}
</a>
</li>
))}
</ul>
</main>
);
}
b. Fetch Private Data (API Route)
// app/api/devto.ts
import { NextResponse } from 'next/server';
export async function GET() {
const res = await fetch('https://dev.to/api/articles/me', {
headers: { 'api-key': process.env.DEV_TO_API_KEY! }
});
const data = await res.json();
return NextResponse.json(data);
}
Usage in React frontend:
useEffect(() => {
fetch('/api/devto')
.then(res => res.json())
.then(setMyArticles)
.catch(console.error);
}, []);
💡 Pro Tips
- Use
per_page
+page
params for pagination control. - Leverage article IDs to fetch full content or stats.
- Combine public & private data for dynamic, rich blog sections in your portfolio.
✅ Final Takeaway
- No API key? Great—fetch public posts directly on the client or server.
- Got a key? Unlock private drafts, metrics, and a complete dashboard—securely, server-side.
- Seamlessly integrate both modes in your Next.js site and showcase a holistic Dev.to-powered blog!
- Visit officials docs Forem
Top comments (3)
It's on their docs already. Thank you for taking time to share it to the public.
You're absolutely right, it’s in the docs.
For Beginners, sometimes a real-world walkthrough makes it easier to implement.
Appreciate you checking it out! 🙌
Thanks