Hashnode GraphQL API
A GraphQL API (Apollo Server) for publishing and managing content on Hashnode:
posts, drafts, publications, users, tags, series, and comments. This skill tells
an agent how to talk to it correctly — endpoint, auth, which operations need a
Pro plan, the limits that cause requests to fail, and where to find the full
field-level reference.
Endpoint
| Environment |
URL |
Path |
| Production |
https://gql-beta.hashnode.com |
/ (POST GraphQL here) |
| Local dev |
http://localhost:8080 |
/graphql |
Standard GraphQL over HTTP POST with a JSON body ({ "query": "...", "variables": {...} }).
Introspection is enabled, so the schema is browsable from any GraphQL IDE.
Authentication
Auth uses a Personal Access Token (PAT). The token must be provided via the
HASHNODE_PAT environment variable and passed by reference at execution time —
never inline the literal token value:
curl -H "Authorization: Bearer $HASHNODE_PAT" ...
Get a PAT from the Hashnode dashboard (Account Settings → Developer / API tokens)
and export it in the shell: export HASHNODE_PAT=....
Token handling rules — the PAT is a password. It grants full write access to
the user's publications (publish, edit, delete):
Never ask the user to paste the token into the conversation. If HASHNODE_PAT
is unset, tell the user to export it in their shell and retry.
Never print, echo, or log the token, and never expand it into a command string —
always let the shell interpolate $HASHNODE_PAT inside the request itself.
Never write the token into files, scripts, or commits.
Public reads need no token: post, feed, user, tag, publication,
documentationProject, checkCustomDomainAvailability, checkSubdomainAvailability.
Authenticated operations need a valid PAT: me, draft, scheduledPost,
and every mutation. A missing/invalid token returns UNAUTHENTICATED.
See references/auth-and-roles.md for the role model
(OWNER / EDITOR / CONTRIBUTOR) and the contributor review workflow.
Pro plan gating
Some operations require the target publication to have an active Pro plan.
This is keyed to the publication, not the calling user. When the publication is
not Pro, the API returns:
{
"errors": [{
"message": "Publication does not have an active Pro plan. Upgrade in your dashboard to access this via the API.",
"extensions": { "code": "FORBIDDEN" }
}]
}
When you see this, tell the user the publication needs to upgrade to Pro in the
Hashnode dashboard. Do not retry the request — it will keep failing until the
publication is on Pro.
Pro-gated operations:
- All write mutations:
publishPost, updatePost, createDraft,
updateDraft, publishDraft, submitDraftForReview, rejectDraftSubmission,
deleteDraft.
- Publication-scoped reads:
publication, draft, scheduledPost,
searchPostsOfPublication, topCommenters. (draft and scheduledPost also
require a PAT and authorization; the owning publication must be Pro.)
Public feed/post/user/tag reads are not Pro-gated.
Hashnode also has a Growth Plan (Pro + the AEO toolkit). It adds no new
gates to this API: publication.aeoSettings and post.faq are readable on
the same terms as their parent types, and aeoSettings resolves with
permissive defaults for non-Growth publications (isEnabled tells you
whether the publication actually has the toolkit). See "AEO fields" in
references/queries.md.
Linking to Hashnode pages (never guess URLs)
When you need to link to a post's discussion, a comment, or a profile on
hashnode.com, build the URL from API data using these exact formats. Do not
browse hashnode.com to discover URL schemes, and do not invent paths.
| Page |
URL format |
| Post discussion on hashnode.com |
https://hashnode.com/posts/<slug>/<postId> |
| A specific comment |
https://hashnode.com/posts/<slug>/<postId>/comment/<commentId> |
| User profile |
https://hashnode.com/@<username> |
| Post on the author's own blog |
Use the post's url field from the API; it already resolves the custom domain vs <username>.hashnode.dev |
<slug> and <postId> are the post's slug and id from the API. Both
are required; there is no id-only or slug-only form.
<commentId> is the comment's id from the post's comments connection.
- Legacy paths like
/discussions/post/<id> and /<postId> 404. Never
emit them.
Example: post id: 6a603fb103e2cb323e7851f6, slug: sealed-with-a-kyss-inside-an-android-banking-rat
→ https://hashnode.com/posts/sealed-with-a-kyss-inside-an-android-banking-rat/6a603fb103e2cb323e7851f6
Reference
- references/schema.graphql — full SDL (introspection schema) from
gql-beta: the canonical source for every type, field, argument, and input. Use this when you need exact field names or types; use the curated files below for auth/Pro behavior the schema can't express.
- references/queries.md — all 13 queries: arguments, return types, auth/Pro notes.
- references/mutations.md — all 10 mutations: inputs, payloads, auth/Pro notes.
- references/auth-and-roles.md — PAT setup, public vs. authenticated, roles, contributor review flow.
- references/errors-and-limits.md — error codes, page-size caps, query depth, payload/image limits.
- references/recipes.md — end-to-end examples: publish a post, paginate a feed, upload an image.
Rules for the agent
- Always send
Authorization: Bearer $HASHNODE_PAT (shell-interpolated from the
environment, never the literal token) for me, draft, scheduledPost, and
any mutation. Without it you get UNAUTHENTICATED. Follow the token handling
rules in the Authentication section: don't ask for, print, or persist the token.
- On
FORBIDDEN + the Pro-plan message, stop and tell the user to upgrade the
publication to Pro. Don't retry.
- Respect page-size caps: most connections cap
first at 100, drafts at
50. Asking for more is silently clamped.
- Keep query depth at or below 10 — deeper queries are rejected.
- Tag inputs use slug (e.g.
javascript), max 15 per post/draft.
- Pagination is cursor-based: read
pageInfo.endCursor / pageInfo.hasNextPage,
pass endCursor as the next after.
- Mutations are never cached; queries may be cached for up to ~25s.
- Build hashnode.com links from API data using the formats in "Linking to
Hashnode pages". Never guess or browse for URL schemes.
1---2name: gql-api3description: Query and mutate content on the Hashnode GraphQL API (posts, drafts, publications, users, tags, series, comments). Use when a user wants to read or write data through the Hashnode gql endpoint, needs a reference for a specific query or mutation, is wiring up a Personal Access Token, or hits a "Publication does not have an active Pro plan" / FORBIDDEN error and needs to know an operation is Pro-gated.4---56# Hashnode GraphQL API78A GraphQL API (Apollo Server) for publishing and managing content on Hashnode:9posts, drafts, publications, users, tags, series, and comments. This skill tells10an agent how to talk to it correctly — endpoint, auth, which operations need a11Pro plan, the limits that cause requests to fail, and where to find the full12field-level reference.1314## Endpoint1516| Environment | URL | Path |17|-------------|-----|------|18| Production | `https://gql-beta.hashnode.com` | `/` (POST GraphQL here) |19| Local dev | `http://localhost:8080` | `/graphql` |2021Standard GraphQL over HTTP `POST` with a JSON body (`{ "query": "...", "variables": {...} }`).22Introspection is enabled, so the schema is browsable from any GraphQL IDE.2324## Authentication2526Auth uses a **Personal Access Token (PAT)**. The token must be provided via the27`HASHNODE_PAT` environment variable and passed by reference at execution time —28never inline the literal token value:2930```bash31curl -H "Authorization: Bearer $HASHNODE_PAT" ...32```3334Get a PAT from the Hashnode dashboard (Account Settings → Developer / API tokens)35and export it in the shell: `export HASHNODE_PAT=...`.3637**Token handling rules — the PAT is a password.** It grants full write access to38the user's publications (publish, edit, delete):3940- Never ask the user to paste the token into the conversation. If `HASHNODE_PAT`41 is unset, tell the user to export it in their shell and retry.42- Never print, echo, or log the token, and never expand it into a command string —43 always let the shell interpolate `$HASHNODE_PAT` inside the request itself.44- Never write the token into files, scripts, or commits.4546- **Public reads** need no token: `post`, `feed`, `user`, `tag`, `publication`,47 `documentationProject`, `checkCustomDomainAvailability`, `checkSubdomainAvailability`.48- **Authenticated** operations need a valid PAT: `me`, `draft`, `scheduledPost`,49 and **every mutation**. A missing/invalid token returns `UNAUTHENTICATED`.5051See [references/auth-and-roles.md](references/auth-and-roles.md) for the role model52(OWNER / EDITOR / CONTRIBUTOR) and the contributor review workflow.5354## Pro plan gating5556Some operations require the **target publication** to have an active Pro plan.57This is keyed to the publication, not the calling user. When the publication is58not Pro, the API returns:5960```json61{62 "errors": [{63 "message": "Publication does not have an active Pro plan. Upgrade in your dashboard to access this via the API.",64 "extensions": { "code": "FORBIDDEN" }65 }]66}67```6869**When you see this, tell the user the publication needs to upgrade to Pro in the70Hashnode dashboard. Do not retry the request — it will keep failing until the71publication is on Pro.**7273Pro-gated operations:7475- **All write mutations:** `publishPost`, `updatePost`, `createDraft`,76 `updateDraft`, `publishDraft`, `submitDraftForReview`, `rejectDraftSubmission`,77 `deleteDraft`.78- **Publication-scoped reads:** `publication`, `draft`, `scheduledPost`,79 `searchPostsOfPublication`, `topCommenters`. (`draft` and `scheduledPost` also80 require a PAT and authorization; the owning publication must be Pro.)8182Public feed/post/user/tag reads are **not** Pro-gated.8384Hashnode also has a **Growth Plan** (Pro + the AEO toolkit). It adds no new85gates to this API: `publication.aeoSettings` and `post.faq` are readable on86the same terms as their parent types, and `aeoSettings` resolves with87permissive defaults for non-Growth publications (`isEnabled` tells you88whether the publication actually has the toolkit). See "AEO fields" in89[references/queries.md](references/queries.md).9091## Linking to Hashnode pages (never guess URLs)9293When you need to link to a post's discussion, a comment, or a profile on94hashnode.com, build the URL from API data using these exact formats. Do not95browse hashnode.com to discover URL schemes, and do not invent paths.9697| Page | URL format |98|------|-----------|99| Post discussion on hashnode.com | `https://hashnode.com/posts/<slug>/<postId>` |100| A specific comment | `https://hashnode.com/posts/<slug>/<postId>/comment/<commentId>` |101| User profile | `https://hashnode.com/@<username>` |102| Post on the author's own blog | Use the post's `url` field from the API; it already resolves the custom domain vs `<username>.hashnode.dev` |103104- `<slug>` and `<postId>` are the post's `slug` and `id` from the API. **Both105 are required**; there is no id-only or slug-only form.106- `<commentId>` is the comment's `id` from the post's `comments` connection.107- Legacy paths like `/discussions/post/<id>` and `/<postId>` **404**. Never108 emit them.109110Example: post `id: 6a603fb103e2cb323e7851f6`, `slug: sealed-with-a-kyss-inside-an-android-banking-rat`111→ `https://hashnode.com/posts/sealed-with-a-kyss-inside-an-android-banking-rat/6a603fb103e2cb323e7851f6`112113## Reference114115- [references/schema.graphql](references/schema.graphql) — full SDL (introspection schema) from `gql-beta`: the canonical source for every type, field, argument, and input. Use this when you need exact field names or types; use the curated files below for auth/Pro behavior the schema can't express.116- [references/queries.md](references/queries.md) — all 13 queries: arguments, return types, auth/Pro notes.117- [references/mutations.md](references/mutations.md) — all 10 mutations: inputs, payloads, auth/Pro notes.118- [references/auth-and-roles.md](references/auth-and-roles.md) — PAT setup, public vs. authenticated, roles, contributor review flow.119- [references/errors-and-limits.md](references/errors-and-limits.md) — error codes, page-size caps, query depth, payload/image limits.120- [references/recipes.md](references/recipes.md) — end-to-end examples: publish a post, paginate a feed, upload an image.121122## Rules for the agent1231241. Always send `Authorization: Bearer $HASHNODE_PAT` (shell-interpolated from the125 environment, never the literal token) for `me`, `draft`, `scheduledPost`, and126 any mutation. Without it you get `UNAUTHENTICATED`. Follow the token handling127 rules in the Authentication section: don't ask for, print, or persist the token.1282. On `FORBIDDEN` + the Pro-plan message, stop and tell the user to upgrade the129 publication to Pro. Don't retry.1303. Respect page-size caps: most connections cap `first` at **100**, drafts at131 **50**. Asking for more is silently clamped.1324. Keep query depth at or below **10** — deeper queries are rejected.1335. Tag inputs use **slug** (e.g. `javascript`), max **15** per post/draft.1346. Pagination is cursor-based: read `pageInfo.endCursor` / `pageInfo.hasNextPage`,135 pass `endCursor` as the next `after`.1367. Mutations are never cached; queries may be cached for up to ~25s.1378. Build hashnode.com links from API data using the formats in "Linking to138 Hashnode pages". Never guess or browse for URL schemes.