ForumBacklinks.org
150k Backlinks manually placed for 11 years
Demo

Forumbacklinks

API documentation

This API places a backlink for a page you send us.

First, create an API key. Then create a task. You can create a task in two ways.

  1. The first way is to ID a specific donor. Get ID from List donors. The list includes the domain rating of each donor, so you know the rating of that donor.
  2. The second way is to create the task without a donor ID. Then our team decides where to place the link. Send us a domain rating range. We will find a forum and place a link.

Create the task with Create task. The response includes the task id.

Then:

  1. You can call Task status with task id and check the status yourself,
  2. or set up a webhook so we send the task status to you.

To create a task we need:

  1. keyword
  2. Target URL for backlink
  3. the domain rating range.
                          Create task
                            keyword
                           target URL
                      domain rating range
                               |
         +---------------------+---------------------+
         |                                           |
         v                                           v
  Get Donors List                            Set Dr from Dr to
   Send donor ID                               Set Language
 Set Dr from Dr to                       our team picks best value
   Set Language                                  the forum
         |                                           |
         +---------------------+---------------------+
                               |
                               v
                       response: task id
                               |
         +---------------------+---------------------+
         |                                           |
         v                                           v
 call Task status                              webhook sends
 with the task id                             the task status
GET200/v1/donors

List donors

Enabled forums only. Each row has its language and our domain rating.

Headers

NameTypeRequiredDescription
AuthorizationstringyesBearer API key created in the account after sign-in

Query params

NameTypeRequiredDescription
languagestringnoOptional language filter. Allowed: DUTCH, ENGLISH, FRENCH, GERMAN, ITALIAN, JAPANESE, POLISH, PORTUGUESE, SPANISH, VIETNAMESE
drFromnumbernoOptional DR lower bound. Send it together with drTo. Must be at least 10
drTonumbernoOptional DR upper bound

No request body.

Response

object

Response fields

NameTypeRequiredDescription
donorsarrayyesEnabled donors
donors[].idnumberyesPass this value as donorId on POST /v1/tasks
donors[].domainstringyesDonor site domain
donors[].languagestringyesDonor language, such as ENGLISH or GERMAN
donors[].domainRatingnumbernoOur domain rating from ahrefs_domain_rating. Omitted when that field is empty

Request

curl -sS "https://api.forumbacklinks.org/v1/donors?language=ENGLISH&drFrom=10&drTo=50" \
  -H "Authorization: Bearer your_key"

Response

{
  "donors": [
    {
      "id": 776,
      "domain": "180degreehealth.com",
      "language": "ENGLISH",
      "domainRating": 42
    },
    {
      "id": 793,
      "domain": "360mate.com",
      "language": "ENGLISH",
      "domainRating": 12
    }
  ]
}

Only forums with available = 1 are returned. Disabled forums are omitted. language is the stored language code, such as ENGLISH or GERMAN. domainRating is our ahrefs_domain_rating. It is omitted when that field is empty. A DR filter uses that same field and drops forums that do not have it.

POST201/v1/tasks

Create a link task

Create a placement for a page URL. Send a forum id, or a forum domain-rating range.

Headers

NameTypeRequiredDescription
AuthorizationstringyesBearer API key created in the account after sign-in
Content-Typestringyesapplication/json

Body

NameTypeRequiredDescription
keywordstringyesAnchor text. 1 to 100 characters
urlstringyeshttp or https page that should receive the placement
donorIdnumbernoOptional id from GET /v1/donors. The donor must be enabled. When sent, that donor stays pinned
drFromnumbernoOptional DR lower bound. Send it together with drTo. Must be at least 10. A lower rating can have no donor
drTonumbernoOptional DR upper bound. Must be greater than or equal to drFrom and no higher than the highest enabled donor rating

Response

object

Response fields

NameTypeRequiredDescription
statusstringyesLink task created successfully
taskIdnumberyesId to keep and pass to GET /v1/tasks/{taskId}/status

Request

curl -sS -X POST https://api.forumbacklinks.org/v1/tasks \
  -H "Authorization: Bearer your_key" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"apply for immortality","url":"https://www.macleod.com/immortality-application","drFrom":30,"drTo":50}'

Response

{
  "status": "Link task created successfully",
  "taskId": 20505
}

Send donorId to pin one enabled forum, or drFrom and drTo together to ask for a rating range. Omit both to leave the forum empty for a later manual pick. A donorId that is missing or not enabled returns 400. When both a forum and a range are sent, our ahrefs_domain_rating must fall inside the range. drFrom must be at least 10. A lower rating can have no donor. drTo cannot be above the highest enabled donor rating. Each POST creates a new task. Read it with GET /v1/tasks/{taskId}/status.

GET200/v1/tasks/{taskId}/status

Get task status

Read one task by the task id from create.

Connect a webhook

Headers

NameTypeRequiredDescription
AuthorizationstringyesBearer API key created in the account after sign-in

Path params

NameTypeRequiredDescription
taskIdnumberyestaskId returned when the task was created

No request body.

Response

object

Response fields

NameTypeRequiredDescription
statusstringyesNEW, IN_PROGRESS, PENDING, REJECTED, COMPLETED, or DELETED
keywordstringyesAnchor text
targetUrlstringyesPage that should receive the placement
resultUrlstringnoPublished placement URL. Present when the task has a result
warrantyUpTostringnoISO timestamp. Present when a warranty end is stored
createdAtstringyesISO timestamp
updatedAtstringyesISO timestamp

Request

curl -sS https://api.forumbacklinks.org/v1/tasks/20505/status \
  -H "Authorization: Bearer your_key"

Response

{
  "status": "COMPLETED",
  "keyword": "apply for immortality",
  "targetUrl": "https://www.macleod.com/immortality-application",
  "resultUrl": "https://www.theimmortals.club/threads/how-to-join-the-highlanders.112358/",
  "warrantyUpTo": "2025-10-23T10:10:32.812Z",
  "createdAt": "2025-09-22T09:53:11.270Z",
  "updatedAt": "2025-09-23T10:10:32.880Z"
}

Poll with the task id returned by create. Statuses: NEW, IN_PROGRESS, PENDING, REJECTED, COMPLETED, DELETED. resultUrl and warrantyUpTo are omitted until they are stored. Unknown task returns 404.

DELETE200/v1/tasks/{taskId}

Delete a task

You can delete a task only while its status is NEW. Any other status cannot be deleted, because our team has already taken that task into work.

Headers

NameTypeRequiredDescription
AuthorizationstringyesBearer API key created in the account after sign-in

Path params

NameTypeRequiredDescription
taskIdnumberyestaskId of a NEW task

No request body.

Response

object

Response fields

NameTypeRequiredDescription
messagestringyesLink task deleted successfully

Request

curl -sS -X DELETE https://api.forumbacklinks.org/v1/tasks/20505 \
  -H "Authorization: Bearer your_key"

Response

{
  "message": "Link task deleted successfully"
}

Only status NEW can be deleted. Any other status returns 400, because that task is already in work with our team. After a successful delete, GET status returns DELETED.

API tests

You can test your application with the same tests.

TestResultRequestResponse
Donors ENGLISH, DR 80–88HTTP 200, 4 forumsGET /v1/donors?language=ENGLISH&drFrom=80&drTo=88{"donors":[{"id":3079,"domain":"chess.com","language":"ENGLISH","domainRating":85},{"id":3193,"domain":"forums.gentoo.org","language":"ENGLISH","domainRating":85},{"id":2679,"domain":"software.informer.com","language":"ENGLISH","domainRating":84},{"id":647,"domain":"support.nabble.com","language":"ENGLISH","domainRating":81}]}
Donors, language KLINGONHTTP 400GET /v1/donors?language=KLINGON{"detail":"Unsupported language KLINGON. Allowed: DUTCH, ENGLISH, FRENCH, GERMAN, ITALIAN, JAPANESE, POLISH, PORTUGUESE, RUSSIAN, SPANISH, VIETNAMESE."}
Donors with only drFromHTTP 400GET /v1/donors?drFrom=10{"detail":"drFrom and drTo must be sent together."}
POST /v1/donorsHTTP 405POST /v1/donors {}{"detail":"Method not allowed."}
GET /v1/tasksHTTP 405GET /v1/tasks{"detail":"Method not allowed."}
Task: keyword and urlHTTP 201, taskId 16POST /v1/tasks {"keyword":"pass3 url only","url":"https://www.pass3-cycle.example/immortality-application"}{"status":"Link task created successfully","taskId":16}
Task: DR 30–50HTTP 201, taskId 17POST /v1/tasks {"keyword":"pass3 dr range","url":"https://pass3-range.example/join","drFrom":30,"drTo":50}{"status":"Link task created successfully","taskId":17}
Task: DR below 30HTTP 400POST /v1/tasks {"keyword":"pass3 dr below","url":"https://pass3-below.example/join","drFrom":20,"drTo":50}{"detail":"drFrom and drTo must stay inside the enabled donor rating range 30 to 88."}
Task: DR above 88HTTP 400POST /v1/tasks {"keyword":"pass3 dr above","url":"https://pass3-above.example/join","drFrom":80,"drTo":89}{"detail":"drFrom and drTo must stay inside the enabled donor rating range 30 to 88."}
Task: DR edges 30–88HTTP 201, taskId 18POST /v1/tasks {"keyword":"pass3 dr edges","url":"https://pass3-edges.example/join","drFrom":30,"drTo":88}{"status":"Link task created successfully","taskId":18}
Task: donor 3079 and DR 80–88HTTP 201, taskId 19POST /v1/tasks {"keyword":"pass3 donor in range","url":"https://pass3-donor.example/join","donorId":3079,"drFrom":80,"drTo":88}{"status":"Link task created successfully","taskId":19}
Task: donor 3079 onlyHTTP 201, taskId 20POST /v1/tasks {"keyword":"pass3 donor only","url":"https://pass3-donor-only.example/join","donorId":3079}{"status":"Link task created successfully","taskId":20}
Donor 3079 outside DR 30–50HTTP 400POST /v1/tasks {"keyword":"pass3 donor outside","url":"https://pass3-outside.example/join","donorId":3079,"drFrom":30,"drTo":50}{"detail":"donor domain rating is outside drFrom and drTo."}
Catalog 4171HTTP 400POST /v1/tasks {"keyword":"pass3 catalog donor","url":"https://pass3-catalog.example/join","donorId":4171}{"detail":"donorId is not an enabled donor."}
Donor 99999999HTTP 400POST /v1/tasks {"keyword":"pass3 unknown donor","url":"https://pass3-unknown.example/join","donorId":99999999}{"detail":"donorId is not an enabled donor."}
Task with only drFromHTTP 400POST /v1/tasks {"keyword":"pass3 half range","url":"https://pass3-half.example/join","drFrom":30}{"detail":"drFrom and drTo must be sent together."}
Task with drFrom above drToHTTP 400POST /v1/tasks {"keyword":"pass3 inverted range","url":"https://pass3-inverted.example/join","drFrom":50,"drTo":30}{"detail":"drFrom must be less than or equal to drTo."}
Task with drTo 101HTTP 400POST /v1/tasks {"keyword":"pass3 dr 101","url":"https://pass3-dr101.example/join","drFrom":30,"drTo":101}{"detail":"drFrom and drTo must be integers from 0 to 100."}
Task without a keywordHTTP 400POST /v1/tasks {"url":"https://pass3-nokeyword.example/join"}{"detail":"keyword is required."}
Task without a urlHTTP 400POST /v1/tasks {"keyword":"pass3 no url"}{"detail":"url is required."}
Task with an ftp urlHTTP 400POST /v1/tasks {"keyword":"pass3 bad scheme","url":"ftp://pass3-ftp.example/join"}{"detail":"url must be an http(s) URL."}
Task with a 101-character keywordHTTP 400POST /v1/tasks {"keyword":"k"×101,"url":"https://pass3-long.example/join"}{"detail":"keyword must be at most 100 characters."}
Task with price 77HTTP 201, taskId 21POST /v1/tasks {"keyword":"pass3 price ignored","url":"https://pass3-price.example/join","price":77}{"status":"Link task created successfully","taskId":21}
Status of task 16HTTP 200GET /v1/tasks/16/status{"status":"NEW","keyword":"pass3 url only","targetUrl":"https://www.pass3-cycle.example/immortality-application","createdAt":"2026-10-08T11:31:14.479Z","updatedAt":"2026-10-08T11:31:14.479Z"}
Status of 99999999HTTP 404GET /v1/tasks/99999999/status{"detail":"Task not found."}
Reject task 16 while NEWHTTP 400PATCH /v1/tasks/16/reject {"reason":"Too early"}{"detail":"Task can be rejected only while its status is COMPLETED."}
Reject with an empty reasonHTTP 400PATCH /v1/tasks/16/reject {"reason":""}{"detail":"reason is required."}
Reject with a 256-character reasonHTTP 400PATCH /v1/tasks/20/reject {"reason":"r"×256}{"detail":"reason must be at most 255 characters."}
Delete task 17HTTP 200DELETE /v1/tasks/17{"message":"Link task deleted successfully"}
Delete task 17 againHTTP 400DELETE /v1/tasks/17{"detail":"Task can be deleted only while its status is NEW."}
Delete 99999999HTTP 404DELETE /v1/tasks/99999999{"detail":"Task not found."}
Reject task 19 after COMPLETEDHTTP 200PATCH /v1/tasks/19/reject {"reason":"Only Adrian Paul counts as a real Highlander. Please fix the page."}{"message":"Link task sent for rework successfully"}
Webhook for creating task 16HTTP 200POST webhook {"taskId":16,"status":"NEW","keyword":"pass3 url only","targetUrl":"https://www.pass3-cycle.example/immortality-application","createdAt":"2026-10-08T11:31:14.479Z","updatedAt":"2026-10-08T11:31:14.479Z"}{"received":true,"stored":true,"taskId":16,"status":"NEW"}
Webhook for creating task 17HTTP 200POST webhook {"taskId":17,"status":"NEW","keyword":"pass3 dr range","targetUrl":"https://pass3-range.example/join","createdAt":"2026-10-08T11:31:15.515Z","updatedAt":"2026-10-08T11:31:15.515Z"}{"received":true,"stored":true,"taskId":17,"status":"NEW"}
Webhook for creating task 18HTTP 200POST webhook {"taskId":18,"status":"NEW","keyword":"pass3 dr edges","targetUrl":"https://pass3-edges.example/join","createdAt":"2026-10-08T11:31:17.670Z","updatedAt":"2026-10-08T11:31:17.670Z"}{"received":true,"stored":true,"taskId":18,"status":"NEW"}
Webhook for creating task 19HTTP 200POST webhook {"taskId":19,"status":"NEW","keyword":"pass3 donor in range","targetUrl":"https://pass3-donor.example/join","createdAt":"2026-10-08T11:31:19.258Z","updatedAt":"2026-10-08T11:31:19.258Z"}{"received":true,"stored":true,"taskId":19,"status":"NEW"}
Webhook for creating task 20HTTP 200POST webhook {"taskId":20,"status":"NEW","keyword":"pass3 donor only","targetUrl":"https://pass3-donor-only.example/join","createdAt":"2026-10-08T11:31:20.321Z","updatedAt":"2026-10-08T11:31:20.321Z"}{"received":true,"stored":true,"taskId":20,"status":"NEW"}
Webhook for creating task 21HTTP 200POST webhook {"taskId":21,"status":"NEW","keyword":"pass3 price ignored","targetUrl":"https://pass3-price.example/join","createdAt":"2026-10-08T11:31:27.088Z","updatedAt":"2026-10-08T11:31:27.088Z"}{"received":true,"stored":true,"taskId":21,"status":"NEW"}
Webhook for deleting task 17HTTP 200POST webhook {"taskId":17,"status":"DELETED","keyword":"pass3 dr range","targetUrl":"https://pass3-range.example/join","createdAt":"2026-10-08T11:31:15.515Z","updatedAt":"2026-10-08T11:31:30.298Z"}{"received":true,"stored":true,"taskId":17,"status":"DELETED"}
Webhook for rejecting task 19HTTP 200POST webhook {"taskId":19,"status":"REJECTED","keyword":"pass3 donor in range","targetUrl":"https://pass3-donor.example/join","createdAt":"2026-10-08T11:31:19.258Z","updatedAt":"2026-10-08T11:31:34.983Z"}{"received":true,"stored":true,"taskId":19,"status":"REJECTED"}
Event for task 16NEWSELECT client_webhook_events task_id=16{"task_id":16,"status":"NEW","body":{"taskId":16,"status":"NEW","keyword":"pass3 url only","targetUrl":"https://www.pass3-cycle.example/immortality-application","createdAt":"2026-10-08T11:31:14.479Z","updatedAt":"2026-10-08T11:31:14.479Z"}}
Event for task 17DELETEDSELECT client_webhook_events task_id=17{"task_id":17,"status":"DELETED","body":{"taskId":17,"status":"DELETED","keyword":"pass3 dr range","targetUrl":"https://pass3-range.example/join","createdAt":"2026-10-08T11:31:15.515Z","updatedAt":"2026-10-08T11:31:30.298Z"}}
Event for task 19REJECTEDSELECT client_webhook_events task_id=19{"task_id":19,"status":"REJECTED","body":{"taskId":19,"status":"REJECTED","keyword":"pass3 donor in range","targetUrl":"https://pass3-donor.example/join","createdAt":"2026-10-08T11:31:19.258Z","updatedAt":"2026-10-08T11:31:34.983Z"}}
taskId 0 in eventsno rowSELECT client_webhook_events task_id=0[]
price in the databasenullSELECT api_tasks id=21{"id":21,"keyword":"pass3 price ignored","status":"NEW","price":null,"donor_id":null,"dr_from":null,"dr_to":null,"target_url":"https://pass3-price.example/join"}
DR after deleteDELETED, 30–50SELECT api_tasks id=17{"id":17,"keyword":"pass3 dr range","status":"DELETED","price":null,"donor_id":null,"dr_from":30,"dr_to":50,"target_url":"https://pass3-range.example/join"}
Donor in the database3079SELECT api_tasks id=20{"id":20,"keyword":"pass3 donor only","status":"NEW","price":null,"donor_id":3079,"dr_from":null,"dr_to":null,"target_url":"https://pass3-donor-only.example/join"}
Host with wwwkeptSELECT projects domain='www.pass3-cycle.example'[{"domain":"www.pass3-cycle.example"}]

COMPLETED for task 19 was set in the database before the reject. There is no public method that marks a task COMPLETED. Requests that return HTTP 400 are not stored and are not sent to the webhook. A later webhook for the same taskId replaces the stored status: task 17 became DELETED, and task 19 became REJECTED. The catalog trustpilot.com (4171) is not in the donor list and is not accepted as a donorId.