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/"
Programs can read this forum's questions, answers, tags and members as JSON, and members can post through it with a personal access token.
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.
{"data": [...], "next": "…"}; one object is returned as it is.id, its address on the site (url) and, when it has one, its address in the API (api_url).2026-03-01T09:30:00+01:00.html, as shown on the site) and their Markdown source (markdown).curl "https://openforis.support/api/v1/questions/1"
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"
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.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).
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.ETag. Send it back in If-None-Match and you get 304 Not Modified when nothing changed.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"]}
}
| Status | Type | Title |
|---|---|---|
| 400 | bad-request | Bad request |
| 401 | unauthorized | Authentication required |
| 401 | invalid-token | Invalid token |
| 403 | insufficient-scope | Insufficient scope |
| 403 | forbidden | Not allowed |
| 403 | account-suspended | Account suspended |
| 403 | email-confirmation-required | Email confirmation required |
| 403 | captcha-required | Use the web site |
| 403 | writes-disabled | Writing through the API is turned off |
| 404 | not-found | Not found |
| 405 | method-not-allowed | Method not allowed |
| 409 | conflict | Conflict |
| 413 | payload-too-large | Request body too large |
| 415 | unsupported-media-type | Unsupported media type |
| 422 | validation-error | Invalid data |
| 422 | spam | Looks like spam |
| 429 | rate-limited | Too many requests |
| 429 | posting-limit | Posting limit reached |
| 500 | server-error | Server error |
| 503 | api-disabled | The API is turned off |
The index and this document.
/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/"
/api/v1/openapi.jsonOpenAPI document
This API described as OpenAPI 3.1, generated from the code.
No token.
curl "https://openforis.support/api/v1/openapi.json"
Lists, search, one question with its answers and comments; asking and following.
/api/v1/questionsList 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).
| Name | Type | Description |
|---|---|---|
tagsquery |
string | Only questions with every one of these tags (names separated by spaces or commas; synonyms work). |
statusquery |
unanswered | answered | accepted | unanswered, answered or accepted (has an accepted answer). |
sortquery |
active | newest | votes | active (latest activity), newest (asked) or votes (score). |
sincequery |
date-time | Only questions with activity (asked, answered, commented, edited) at or after this date or time (ISO 8601). |
limitquery |
integer | Items per page. |
cursorquery |
string | Where 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"
/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).
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The question id. |
Answer (200): Question
Errors: 404 not-found, 401 invalid-token, 429 rate-limited
curl "https://openforis.support/api/v1/questions/1"
/api/v1/searchSearch questions
The site search (full text, best matches first) with the filters of the search page. Returns at most limit results (next is always null). Only published questions are found.
Token optional (with one you also see your own posts waiting for review).
| Name | Type | Description |
|---|---|---|
q requiredquery |
string | What to look for. The search operators work: "a phrase", -word, [tag], user:name, is:answered. |
tagsquery |
string | Every one of these tags. |
statusquery |
unanswered | answered | accepted | unanswered, answered or accepted. |
closedquery |
hide | hide leaves out closed questions. |
datequery |
week | month | year | Asked in the last week, month or year. |
fromquery |
date | Asked on or after (YYYY-MM-DD). |
toquery |
date | Asked on or before (YYYY-MM-DD). |
authorquery |
string | Asked by this member (username). |
codequery |
1 | The question or an answer has a code block. |
min_scorequery |
integer | A score of at least this. |
versionquery |
string | The question or one of its answers applies to this version (of the given tags, if any). |
limitquery |
integer | How many results. |
Answer (200): QuestionPage
Errors: 400 bad-request, 401 invalid-token, 429 rate-limited
curl "https://openforis.support/api/v1/search?q=export+csv"
/api/v1/questionsAsk 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"]}'
/api/v1/questions/{id}/followFollow 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.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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"
/api/v1/questions/{id}/followStop following a question
Needs a token with the write scope.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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 DELETE "https://openforis.support/api/v1/questions/1/follow" \ -H "Authorization: Bearer $OSQA_TOKEN"
Answers of a question, one answer; answering and accepting.
/api/v1/questions/{id}/answersA 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).
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The question id. |
Answer (200): AnswerList
Errors: 404 not-found, 401 invalid-token, 429 rate-limited
curl "https://openforis.support/api/v1/questions/1/answers"
/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).
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The answer id. |
Answer (200): Answer
Errors: 404 not-found, 401 invalid-token, 429 rate-limited
curl "https://openforis.support/api/v1/answers/1"
/api/v1/questions/{id}/answersAnswer a question
Closed and deleted questions take no answers.
Needs a token with the write scope.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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."}'
/api/v1/answers/{id}/acceptAccept 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.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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"
/api/v1/answers/{id}/acceptTake an acceptance back
Needs a token with the write scope.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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
curl -X DELETE "https://openforis.support/api/v1/answers/1/accept" \ -H "Authorization: Bearer $OSQA_TOKEN"
Commenting on questions and answers.
/api/v1/posts/{id}/commentsComment 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.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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?"}'
Voting on questions and answers.
/api/v1/posts/{id}/voteVote 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.
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The 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 and their synonyms.
/api/v1/tagsList tags
Tags in use, with their synonyms.
Token optional (with one you also see your own posts waiting for review).
| Name | Type | Description |
|---|---|---|
qquery |
string | Only tags whose name contains this. |
sortquery |
popular | name | popular or name. |
limitquery |
integer | Items per page. |
cursorquery |
string | Where 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"
/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).
| Name | Type | Description |
|---|---|---|
name requiredpath |
string | The 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"
Public profiles, badges and the token owner.
/api/v1/meThe token's owner
Who the token belongs to, its scopes and expiry.
Needs a token.
Answer (200): Me
Errors: 401 unauthorized, 401 invalid-token, 403 account-suspended
curl "https://openforis.support/api/v1/me" \ -H "Authorization: Bearer $OSQA_TOKEN"
/api/v1/usersList members
Public profile fields only.
Token optional (with one you also see your own posts waiting for review).
| Name | Type | Description |
|---|---|---|
qquery |
string | Only members whose username contains this. |
sortquery |
reputation | newest | name | reputation, newest or name. |
limitquery |
integer | Items per page. |
cursorquery |
string | Where 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"
/api/v1/users/{id}A member's public profile
Token optional (with one you also see your own posts waiting for review).
| Name | Type | Description |
|---|---|---|
id requiredpath |
integer | The member id. |
Answer (200): User
Errors: 404 not-found, 401 invalid-token, 429 rate-limited
curl "https://openforis.support/api/v1/users/1"
/api/v1/badgesList 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"
A member, as shown next to posts.
| Field | Type | Description |
|---|---|---|
id |
integer | |
username |
string | |
url |
uri | |
reputation |
integer |
A public profile.
| Field | Type | Description |
|---|---|---|
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 |
| Field | Type | Description |
|---|---|---|
user |
User | |
token |
object {name, scopes, expires} |
| Field | Type | Description |
|---|---|---|
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). |
The version of a tagged product a post applies to.
| Field | Type | Description |
|---|---|---|
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 |
| Field | Type | Description |
|---|---|---|
id |
integer | |
post_id |
integer | |
url |
uri | |
score |
integer | |
author |
UserBrief or null | |
created |
date-time | |
html |
string | |
markdown |
string | |
held_for_review |
boolean |
| Field | Type | Description |
|---|---|---|
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 |
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:
| Field | Type | Description |
|---|---|---|
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 |
| Field | Type | Description |
|---|---|---|
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 |
| Field | Type | Description |
|---|---|---|
id |
integer | |
name |
string | |
description |
string | |
type |
gold | silver | bronze | |
awarded_count |
integer | |
url |
uri |
| Field | Type | Description |
|---|---|---|
post_id |
integer | |
vote |
up | down or null | |
score |
integer | |
votes_left |
integer | Votes you can still cast in the next 24 hours. |
| Field | Type | Description |
|---|---|---|
question_id |
integer | |
following |
boolean |
| Field | Type | Description |
|---|---|---|
name |
string | |
version |
string | |
docs |
uri | |
openapi |
uri | |
links |
object |
An error (RFC 9457, application/problem+json).
| Field | Type | Description |
|---|---|---|
type |
uri | |
title |
string | |
status |
integer | |
detail optional |
string | |
instance optional |
string | |
errors optional |
object | Messages per field or parameter (validation-error, bad-request). |
A list: the items, and the URL of the next page (null on the last page).
| Field | Type | Description |
|---|---|---|
data |
list of QuestionSummary | |
next |
uri or null |
A list: the items, and the URL of the next page (null on the last page).
| Field | Type | Description |
|---|---|---|
data |
list of Answer | |
next |
uri or null |
A list: the items, and the URL of the next page (null on the last page).
| Field | Type | Description |
|---|---|---|
data |
list of Tag | |
next |
uri or null |
A list: the items, and the URL of the next page (null on the last page).
| Field | Type | Description |
|---|---|---|
data |
list of User | |
next |
uri or null |
A list: the items, and the URL of the next page (null on the last page).
| Field | Type | Description |
|---|---|---|
data |
list of Badge | |
next |
uri or null |
| Field | Type | Description |
|---|---|---|
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). |
| Field | Type | Description |
|---|---|---|
text |
string | Markdown. |
wiki optional |
boolean |
| Field | Type | Description |
|---|---|---|
text |
string |
| Field | Type | Description |
|---|---|---|
vote |
up | down | none | none takes your vote back. |