API documentation

Programs can read this forum's questions, answers, tags and members as JSON, and members can post through it with a personal access token.

Basics

Every address starts with https://openforis.support/api/v1/. The same reference is available as an OpenAPI 3.1 document, for code generators and API tools.

  • Answers are JSON (UTF-8). A list is an object {"data": [...], "next": "…"}; one object is returned as it is.
  • Every object has its id, its address on the site (url) and, when it has one, its address in the API (api_url).
  • Dates are ISO 8601 with the site's UTC offset, e.g. 2026-03-01T09:30:00+01:00.
  • Posts come with their rendered HTML (html, as shown on the site) and their Markdown source (markdown).
  • You see what the site shows you: deleted posts and posts waiting for a moderator are left out, except your own when you send your token.
curl "https://openforis.support/api/v1/questions/1"

Authentication

Reading needs no token. To post, vote or follow questions, and to see your own posts that wait for review, send a personal access token in the Authorization header:

curl -H "Authorization: Bearer $OSQA_TOKEN" "https://openforis.support/api/v1/me"
  • Sign in, then create tokens in your settings, under API tokens. A token is shown once: copy it then. Only a fingerprint of it is stored.
  • A token has the read scope, or read and write. It acts as you: the same reputation rules, posting limits, email confirmation and review of first posts apply as on the site.
  • Tokens expire after the time you choose, and you can revoke one at any time.
  • The API never uses the sign-in cookie of the site: without a token you are an anonymous visitor, and nothing can be changed.

Rate limits

  • Without a token: 60 requests per minute per IP address.
  • With a token: 300 requests per minute per token. Of those, at most 30 changes (posts, votes, accepts, follows).

Each answer tells where you stand: X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (seconds until the minute starts again). Over the limit, the answer is 429 with Retry-After (seconds). The site's hourly limits on questions, answers and comments also apply (429, posting-limit).

Pages and caching

  • Lists take limit (1 to 100). next is the address of the next page (also in a Link: <…>; rel="next" header), or null on the last page. Follow it as it is: its cursor stays valid when new posts arrive.
  • Single objects carry an ETag. Send it back in If-None-Match and you get 304 Not Modified when nothing changed.
  • Web pages on other sites can read the API with JavaScript (CORS, GET only, without cookies) from: *.

Errors

Errors are problem details (RFC 9457, application/problem+json): type (one of the addresses below), title, status, detail (what went wrong, in the language of Accept-Language) and, for invalid data, errors per field.

{
  "type": "https://openforis.support/api/#problem-validation-error",
  "title": "Invalid data",
  "status": 422,
  "detail": "title must be at least 10 characters",
  "errors": {"title": ["title must be at least 10 characters"]}
}
StatusTypeTitle
400bad-requestBad request
401unauthorizedAuthentication required
401invalid-tokenInvalid token
403insufficient-scopeInsufficient scope
403forbiddenNot allowed
403account-suspendedAccount suspended
403email-confirmation-requiredEmail confirmation required
403captcha-requiredUse the web site
403writes-disabledWriting through the API is turned off
404not-foundNot found
405method-not-allowedMethod not allowed
409conflictConflict
413payload-too-largeRequest body too large
415unsupported-media-typeUnsupported media type
422validation-errorInvalid data
422spamLooks like spam
429rate-limitedToo many requests
429posting-limitPosting limit reached
500server-errorServer error
503api-disabledThe API is turned off

Endpoints

About

The index and this document.

GET /api/v1/

API index

Links to the documentation, the OpenAPI document and the lists.

No token.

Answer (200): Index

curl "https://openforis.support/api/v1/"

GET /api/v1/openapi.json

OpenAPI document

This API described as OpenAPI 3.1, generated from the code.

No token.

curl "https://openforis.support/api/v1/openapi.json"

Questions

Lists, search, one question with its answers and comments; asking and following.

GET /api/v1/questions

List questions

Questions the viewer may see, newest activity first by default. Held posts are listed for their author and moderators only, as on the site.

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
tagsquery stringOnly questions with every one of these tags (names separated by spaces or commas; synonyms work).
statusquery unanswered | answered | acceptedunanswered, answered or accepted (has an accepted answer).
sortquery active | newest | votesactive (latest activity), newest (asked) or votes (score).
sincequery date-timeOnly questions with activity (asked, answered, commented, edited) at or after this date or time (ISO 8601).
limitquery integerItems per page.
cursorquery stringWhere the page starts: take it from the next link of the previous page.

Answer (200): QuestionPage

Errors: 400 bad-request, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/questions?tags=collect+export&since=2026-01-31"

GET /api/v1/questions/{id}

A question with its answers and comments

Rendered HTML and Markdown source of every post. Supports If-None-Match (ETag, 304).

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
id requiredpath integerThe question id.

Answer (200): Question

Errors: 404 not-found, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/questions/1"

POST /api/v1/questions

Ask a question

As the ask page: the same length and tag rules, hourly limit and review of first posts (held_for_review is true while a held post waits for a moderator).

Needs a token with the write scope.

Request body: NewQuestion (JSON)

{
  "title": "How do I export survey data to CSV?",
  "text": "I need the data in **R**. Which menu exports it?",
  "tags": [
    "collect",
    "export"
  ]
}

Answer (201): Question

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 403 email-confirmation-required, 403 captcha-required, 422 validation-error, 422 spam, 429 posting-limit

curl -X POST "https://openforis.support/api/v1/questions" \
  -H "Authorization: Bearer $OSQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "How do I export survey data to CSV?", "text": "I need the data in **R**. Which menu exports it?", "tags": ["collect", "export"]}'

POST /api/v1/questions/{id}/follow

Follow a question

Get notified about its new answers and comments, as with the Follow button (by email as set in your email settings).

Needs a token with the write scope.

Parameters
NameTypeDescription
id requiredpath integerThe question id.

Answer (200): Following

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 404 not-found

curl -X POST "https://openforis.support/api/v1/questions/1/follow" \
  -H "Authorization: Bearer $OSQA_TOKEN"

Answers

Answers of a question, one answer; answering and accepting.

GET /api/v1/questions/{id}/answers

A question's answers

Accepted first, then by score, each with its comments (all of them: next is always null).

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
id requiredpath integerThe question id.

Answer (200): AnswerList

Errors: 404 not-found, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/questions/1/answers"

GET /api/v1/answers/{id}

An answer with its comments

Supports If-None-Match (ETag, 304).

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
id requiredpath integerThe answer id.

Answer (200): Answer

Errors: 404 not-found, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/answers/1"

POST /api/v1/questions/{id}/answers

Answer a question

Closed and deleted questions take no answers.

Needs a token with the write scope.

Parameters
NameTypeDescription
id requiredpath integerThe question id.

Request body: NewAnswer (JSON)

{
  "text": "Use **File > Export > CSV** in the designer."
}

Answer (201): Answer

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 404 not-found, 409 conflict, 403 email-confirmation-required, 403 captcha-required, 422 validation-error, 422 spam, 429 posting-limit

curl -X POST "https://openforis.support/api/v1/questions/1/answers" \
  -H "Authorization: Bearer $OSQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Use **File > Export > CSV** in the designer."}'

POST /api/v1/answers/{id}/accept

Accept an answer

The site's limits on accepted answers per question apply. Accepting an accepted answer changes nothing.

Needs a token with the write scope.

Parameters
NameTypeDescription
id requiredpath integerThe answer id.

Answer (200): Answer

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 404 not-found, 409 conflict

curl -X POST "https://openforis.support/api/v1/answers/1/accept" \
  -H "Authorization: Bearer $OSQA_TOKEN"

Comments

Commenting on questions and answers.

POST /api/v1/posts/{id}/comments

Comment on a question or an answer

Needs the reputation to comment (except on your own posts and answers to your question).

Needs a token with the write scope.

Parameters
NameTypeDescription
id requiredpath integerThe question or answer id.

Request body: NewComment (JSON)

{
  "text": "Which version do you use?"
}

Answer (201): Comment

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 404 not-found, 403 email-confirmation-required, 422 validation-error, 422 spam, 429 posting-limit

curl -X POST "https://openforis.support/api/v1/posts/1/comments" \
  -H "Authorization: Bearer $OSQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Which version do you use?"}'

Votes

Voting on questions and answers.

POST /api/v1/posts/{id}/vote

Vote up, down, or take your vote back

Sets your vote to the given value (sending the same value twice changes nothing). The reputation needed for each direction, the votes per day and the time after which a vote can't be taken back are the site's.

Needs a token with the write scope.

Parameters
NameTypeDescription
id requiredpath integerThe question or answer id.

Request body: VoteRequest (JSON)

{
  "vote": "up"
}

Answer (200): Vote

Errors: 401 unauthorized, 401 invalid-token, 403 insufficient-scope, 403 account-suspended, 403 writes-disabled, 403 forbidden, 429 rate-limited, 404 not-found, 409 conflict, 422 validation-error, 429 posting-limit

curl -X POST "https://openforis.support/api/v1/posts/1/vote" \
  -H "Authorization: Bearer $OSQA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"vote": "up"}'

Tags

Tags and their synonyms.

GET /api/v1/tags

List tags

Tags in use, with their synonyms.

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
qquery stringOnly tags whose name contains this.
sortquery popular | namepopular or name.
limitquery integerItems per page.
cursorquery stringWhere the page starts: take it from the next link of the previous page.

Answer (200): TagPage

Errors: 400 bad-request, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/tags"

GET /api/v1/tags/{name}

A tag

A synonym gives the tag it stands for.

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
name requiredpath stringThe tag name (or one of its synonyms).

Answer (200): Tag

Errors: 404 not-found, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/tags/collect"

Members

Public profiles, badges and the token owner.

GET /api/v1/users

List members

Public profile fields only.

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
qquery stringOnly members whose username contains this.
sortquery reputation | newest | namereputation, newest or name.
limitquery integerItems per page.
cursorquery stringWhere the page starts: take it from the next link of the previous page.

Answer (200): UserPage

Errors: 400 bad-request, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/users"

GET /api/v1/users/{id}

A member's public profile

Token optional (with one you also see your own posts waiting for review).

Parameters
NameTypeDescription
id requiredpath integerThe member id.

Answer (200): User

Errors: 404 not-found, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/users/1"

GET /api/v1/badges

List badges

Every badge, gold first (next is always null).

Token optional (with one you also see your own posts waiting for review).

Answer (200): BadgeList

Errors: 400 bad-request, 401 invalid-token, 429 rate-limited

curl "https://openforis.support/api/v1/badges"

Objects

UserBrief

A member, as shown next to posts.

FieldTypeDescription
id integer
username string
url uri
reputation integer

User

A public profile.

FieldTypeDescription
id integer
username string
url uri
api_url uri
reputation integer
real_name string or null
location string or null
website string or null
badges object {gold, silver, bronze}
joined date-time
moderator boolean

Me

FieldTypeDescription
user User
token object {name, scopes, expires}

QuestionSummary

FieldTypeDescription
id integer
url uri
api_url uri
title string
tags list of string
score integer
status unanswered | answered | accepted
answer_count integer
view_count integer
closed boolean
duplicate_of object {id, url, api_url} or null
author UserBrief or null
created date-time
last_activity date-time
held_for_review boolean Waiting for a moderator (shown to its author and moderators only; nobody else sees the post).

PostVersion

The version of a tagged product a post applies to.

FieldTypeDescription
tag string
version string The version of the tagged product the post applies to.
current_version string or null
outdated boolean A newer version than the one it was written (or confirmed) for is current.
confirmed_for object {version, by, at} or null

Comment

FieldTypeDescription
id integer
post_id integer
url uri
score integer
author UserBrief or null
created date-time
html string
markdown string
held_for_review boolean

Answer

FieldTypeDescription
id integer
question_id integer
url uri
api_url uri
score integer
accepted boolean
author UserBrief or null
created date-time
html string The rendered, sanitised HTML shown on the site.
markdown string The Markdown source.
held_for_review boolean
versions list of PostVersion The versions it applies to (empty when none is given).
comments optional list of Comment
my_vote optional up | down or null

Question

A question with its answers (accepted first, then by score) and comments. my_vote and following are given when a token is sent.

Everything in QuestionSummary, and:

FieldTypeDescription
html string
markdown string
deleted boolean
versions list of PostVersion
comments list of Comment
answers list of Answer
my_vote optional up | down or null
following optional boolean

Tag

FieldTypeDescription
name string
url uri
api_url uri
count integer Questions with it.
description string Markdown.
synonyms list of string Names that are stored as this tag.
created date-time or null

Badge

FieldTypeDescription
id integer
name string
description string
type gold | silver | bronze
awarded_count integer
url uri

Vote

FieldTypeDescription
post_id integer
vote up | down or null
score integer
votes_left integer Votes you can still cast in the next 24 hours.

Following

FieldTypeDescription
question_id integer
following boolean

Index

FieldTypeDescription
name string
version string
docs uri
openapi uri
links object

Problem

An error (RFC 9457, application/problem+json).

FieldTypeDescription
type uri
title string
status integer
detail optional string
instance optional string
errors optional object Messages per field or parameter (validation-error, bad-request).

QuestionPage

A list: the items, and the URL of the next page (null on the last page).

FieldTypeDescription
data list of QuestionSummary
next uri or null

AnswerList

A list: the items, and the URL of the next page (null on the last page).

FieldTypeDescription
data list of Answer
next uri or null

TagPage

A list: the items, and the URL of the next page (null on the last page).

FieldTypeDescription
data list of Tag
next uri or null

UserPage

A list: the items, and the URL of the next page (null on the last page).

FieldTypeDescription
data list of User
next uri or null

BadgeList

A list: the items, and the URL of the next page (null on the last page).

FieldTypeDescription
data list of Badge
next uri or null

NewQuestion

FieldTypeDescription
title string
text string Markdown.
tags list of string or string Tag names (a list, or one string separated by spaces).
wiki optional boolean Community wiki (when the site allows it).

NewAnswer

FieldTypeDescription
text string Markdown.
wiki optional boolean

NewComment

FieldTypeDescription
text string

VoteRequest

FieldTypeDescription
vote up | down | none none takes your vote back.

Keyboard shortcuts

Anywhere

?
Show this list
/
Search
g h
Go to the home page
g q
Go to the questions
g t
Go to the tags
g u
Go to the users
a
Ask a question

Lists of questions

j k
Next or previous question
Enter
Open the question

Question pages

j k
Next or previous post

Shortcuts never apply while you type in a text field. Members can turn them off in their preferences.