Forem API V1
dev · Social
Access Forem articles, users and other resources via API. For a real-world example of Forem in action, check out [DEV](https://www.dev.to). All endpoints can be accessed with the 'api-key' header and a accept header, but some of them are accessible publicly without authentication. Dates and date times, unless otherwise specified, must be in the [RFC 3339](https://tools.ietf.org/html/rfc3339) format.
Authentication
Sample Requests
This endpoint allows the client to retrieve a list of articles. "Articles" are all the posts that users create on DEV that typically show up in the feed. They can be a blog post, a discussion question, a help thread etc. but is referred to as article within the code. By default it will return feat
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles?tag=example&top=1&page=1&tags=example&state=fresh&per_page=30&username=testuser&tags_exclude=example&collection_id=1"
import requests
params = {
"tag": "example",
"top": "1",
"page": "1",
"tags": "example",
"state": "fresh",
"per_page": "30",
"username": "testuser",
"tags_exclude": "example",
"collection_id": "1"
}
response = requests.get(
"https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles');
url.searchParams.set('tag', 'example');
url.searchParams.set('top', '1');
url.searchParams.set('page', '1');
url.searchParams.set('tags', 'example');
url.searchParams.set('state', 'fresh');
url.searchParams.set('per_page', '30');
url.searchParams.set('username', 'testuser');
url.searchParams.set('tags_exclude', 'example');
url.searchParams.set('collection_id', '1');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles")
q := baseURL.Query()
q.Set("tag", "example")
q.Set("top", "1")
q.Set("page", "1")
q.Set("tags", "example")
q.Set("state", "fresh")
q.Set("per_page", "30")
q.Set("username", "testuser")
q.Set("tags_exclude", "example")
q.Set("collection_id", "1")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles")
uri.query = URI.encode_www_form({
"tag" => "example",
"top" => "1",
"page" => "1",
"tags" => "example",
"state" => "fresh",
"per_page" => "30",
"username" => "testuser",
"tags_exclude" => "example",
"collection_id" => "1"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/articles?" . http_build_query([
"tag" => "example",
"top" => "1",
"page" => "1",
"tags" => "example",
"state" => "fresh",
"per_page" => "30",
"username" => "testuser",
"tags_exclude" => "example",
"collection_id" => "1"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));This endpoint allows the client to retrieve all comments belonging to an article or podcast episode as threaded conversations. It will return the all top level comments with their nested comments as threads. See the format specification for further details.
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments?a_id=example&p_id=example"
import requests
params = {
"a_id": "example",
"p_id": "example"
}
response = requests.get(
"https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments');
url.searchParams.set('a_id', 'example');
url.searchParams.set('p_id', 'example');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments")
q := baseURL.Query()
q.Set("a_id", "example")
q.Set("p_id", "example")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments")
uri.query = URI.encode_www_form({
"a_id" => "example",
"p_id" => "example"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/comments?" . http_build_query([
"a_id" => "example",
"p_id" => "example"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));This endpoint allows the client to retrieve a list of podcast episodes. "Podcast episodes" are episodes belonging to podcasts. It will only return active (reachable) podcast episodes that belong to published podcasts available on the platform, ordered by descending publication date.
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes?page=1&per_page=30&username=testuser"
import requests
params = {
"page": "1",
"per_page": "30",
"username": "testuser"
}
response = requests.get(
"https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes');
url.searchParams.set('page', '1');
url.searchParams.set('per_page', '30');
url.searchParams.set('username', 'testuser');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes")
q := baseURL.Query()
q.Set("page", "1")
q.Set("per_page", "30")
q.Set("username", "testuser")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes")
uri.query = URI.encode_www_form({
"page" => "1",
"per_page" => "30",
"username" => "testuser"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/dev.to/1.0.0/api/podcast_episodes?" . http_build_query([
"page" => "1",
"per_page" => "30",
"username" => "testuser"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Postman Setup Guide
- See official documentation for authentication and setup.
What can you build with Forem API V1?
Forem API V1 is a Social API. Developers commonly use social APIs for:
- adding social login (Sign in with Google/Twitter)
- fetching user-generated content for analysis
- scheduling and publishing social posts
- tracking mentions and engagement metrics
- building community dashboards
No authentication required. This API is open — no signup or key needed. Ideal for quick prototypes and public-facing features. Forem API V1 is free to use, making it a low-risk choice to experiment with.
New to APIs? Read our beginner's guide · Learn about API keys · What is REST?