NAV Navbar

REST API documentation

shell php

API Reference

Welcome to the BlogIn REST API. The API has a group of endpoints for each item type, such as Members or Posts.

The examples are in php and shell. Use the tabs at the top right to change the language.

To try the API in Postman, download the collection below and import the JSON file into Postman.

After importing, set your API key as the local value of token and configure the resource ID variables using records from your company. Optional query examples are disabled in Params. Send requests individually; POST and DELETE examples change data.

Authentication

Authenticate with an API key. An administrator creates keys on the API tab of the Settings page of your BlogIn account.

The full key shows only once, when you create it. Copy it and keep it safe: BlogIn stores only a hash of the key. New keys start with BLGN_, and the Settings page shows only the start of each key. Keys are case-sensitive. If you lose a key, the administrator who created it can click Regenerate. The key keeps its access and note, the old value stops working at once, and the new value shows once. Other administrators can remove the key and create a new one.

Write-only keys. A Write only key can create, update and delete, but it cannot read stored data. A create or update answers with the usual status (201 or 200), but the body holds only the record id, for example {"id": 123}, and meta.warnings when there are warnings. Such a warning names a locked category by its id, not by its name. Adding a member to a team or removing a member from a team answers {"member_id": 123}. A key with read and write access gets the full record.

Send the API key as a bearer token in the Authorization header.

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);
curl 'https://blogin.co/api/rest/members'
  -H 'Authorization: Bearer {key}'

Request rules

These rules apply to every endpoint.

Partial updates

Every POST update is a partial update. Send only the fields you want to change:

This is similar to JSON merge patch, but it is not RFC 7386: the verb is POST, a null on a field that cannot be cleared is a 400, and a body that is not a JSON object is a 400.

Send write fields in the request body. The API reads the body as JSON, whatever the Content-Type header says. The query string never writes anything: a write field in the query string answers 400 and names the field, for example title must be sent in the request body; this endpoint does not read write fields from the query string.

A response is a valid request. You can read a resource with GET, change some fields, and send the whole document back. Fields you did not change keep their values, and read-only fields are ignored. A post update of this kind sends no notification (see renotify in Update a post).

null, empty and "NULL" values

Value Effect
null Clears the field. A text field, such as a member phone, stores no value. A collection loses every entry. position moves the item to the end. author removes the author. A category parent makes the category a root category. post_poll deletes the poll and its votes.
[] Clears a collection, the same as null. The collections are tags, categories, teams, visibility_teams and post_poll.answers. Send a collection as a JSON list. A JSON object is a 400 and changes nothing, whatever its keys: {"tags": {"a": "news"}}, {"tags": {"0": "news"}} and {"tags": {}} are all refused.
"" A 400 on every field that is not free text: booleans, numbers, dates, collections and objects. Also a 400 on title, category and team name, comment text, email, username and access_level. Omit the field to keep its value.
Stored as an empty string on the member fields name, surname, job_title and phone. On a post or page update, "text": "" clears the content; on a create, text must not be empty.
"NULL" The uppercase text, also with spaces around it, is a 400 on every text field: post and page title and text, comment text, category and team name, member username, name, surname, job_title and phone, every tag name, and the poll question and answer text. Send null to clear a field. "null" and "Null" are stored as text. In a post's categories, a category name is only looked up, so "NULL" is skipped with a warning, like any other unknown name.

Fields that refuse null (400): title, text, every boolean (published, important, wiki, pinned, comments_disabled, approved, notify, renotify, notify_all_users, visible_all_users, locked), category and team name, and member email, username and access_level. Also author.id, except on a post, comment or page without an author (see Update a post). A post date_published accepts null only when the post stays unpublished: {"published": false, "date_published": null} is accepted, and {"published": true, "date_published": null} is a 400.

Sorting

List endpoints take a sort parameter. Each endpoint lists its sort columns. Put @ before the column for ascending order, or - for descending order. Example: GET https://blogin.co/api/rest/members?sort=@surname

Items with the same value in the sort column are ordered by id in the same direction, so each item is on exactly one page. This does not apply to the Usage stats endpoints.

Warnings

Some wrong input does not reject the request. The API skips, changes or ignores the value and adds a message to meta.warnings, an array of strings. Example: {"id": 3562, ..., "meta": {"warnings": ["category id 99 not found, skipped"]}}. When a post create or update has no warnings, the response has no meta key. Each field lists its warnings.

In a response, a post or page text has absolute links to the uploaded images and files of the workspace. Each link has an access token (?gt=…), so it opens outside BlogIn.

When you send text in a create or an update, the API stores these links in their normal form again. It removes a valid access token from every link to the upload folder of this workspace, whatever the address in front of it, because a response adds the token again. It removes the workspace address only from links to this workspace. It stores all other links as you send them. So you can send back the text you received, and the links keep working.

Titles are returned as stored, with emoji as characters, not as images.

Members

Member Properties

Attribute Type Description
id int Unique identifier for the resource. read-only
email string The email address for the member. mandatory
username string Member login name.
name string Member first name.
surname string Member last name.
avatar string Avatar URL. read-only
access_level string Member access level.
In a request, send the name (Administrator, Reviewer, Writer, Commenter, Reader) or its level number ("20", "15", "10", "5", "2", in the same order). Any other value answers 400.
A response returns the level number as a string, for example "20" for Administrator.
Reviewer is available only when content approval is enabled.
job_title string Member job title.
phone string Member phone number.
time_registered date-time Member register time. (ISO-8601 format) read-only
timezone string Member timezone.
status string active or deactivated. read-only
teams array List of Member teams, ordered by team position, then id. See Member - Team properties

Create new member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$member = [
    'email' => 'john.doe@example.com',
    'username' => 'johndoe',
    'name' => 'John',
    'surname' => 'Doe',
    'access_level' => 'Writer',
    'job_title' => 'Developer',
    'phone' => '0123456789',
    'teams' => [
        [
            'id' => 123
        ],
    ]
];

$response = $blogInApi->post('members', ['json' => $member]);
curl --request POST 'https://blogin.co/api/rest/members' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {key}' \
--data-raw '{
    "email": "john.doe@example.com",
    "username": "johndoe",
    "name": "John",
    "surname": "Doe",
    "access_level": "Writer",
    "job_title": "Developer",
    "phone": "0123456789",
    "teams": [
        {
            "id": 123
        }
    ]
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 456,
    "email": "john.doe@example.com",
    "username": "johndoe",
    "name": "John",
    "surname": "Doe",
    "avatar": "https://secure.gravatar.com/avatar/5658ffccee7f0ebfda2b226238b1eb6e?s=90&d=identicon",
    "access_level": "10",
    "job_title": "Developer",
    "phone": "0123456789",
    "time_registered": "2020-03-02T09:47:50+01:00",
    "timezone": "",
    "status": "active",
    "teams": [
        {
            "id": 123,
            "name": "Example Team",
            "position": 0
        }
    ]
}

This API allows you to create a new member.

HTTP Request

POST https://blogin.co/api/rest/members

Request body - JSON format

Parameter Description
email New member email address. mandatory
username New member username. Optional. Allowed characters: A-Z, a-z, digits, _, . and -. Any other value, null and "" answer 400. Omit the field to build the username from the email address.
Maximum 35 characters. The API shortens a longer username and lists the stored name in meta.warnings. When the username is already used in the workspace (letter case is ignored), the API adds a suffix such as .4821 and keeps the total at 35 characters or less. The response returns the stored username.
409: another request took the same username or email at the same moment (send the request again), or no free username was found (send a different username).
name New member name.
surname New member surname.
access_level New member role, by name: Administrator, Reviewer, Writer, Commenter or Reader. Default: Writer.
job_title New member job_title.
phone New member phone.
teams Array of objects with the id of each Team the new member joins, for example [{"id": 123}]. Locked teams are allowed, as for an administrator. The API saves the member, its teams and the signup together: when one part fails, nothing is saved and the request answers 500, so you can send it again.

Get all members

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('members');
$members = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/members'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 797,
            "email": "arianna@example.com",
            "username": "ariana.clay",
            "name": "Ariana",
            "surname": "Clay",
            "avatar": "https://secure.gravatar.com/avatar/a4d5b21c4e7eeb3bd2e8a9d278772ea9?s=90&d=identicon",
            "access_level": "2",
            "job_title": "Engineer",
            "phone": "",
            "time_registered": "2019-12-13T12:46:48+01:00",
            "timezone": "Pacific/Midway",
            "status": "active",
            "teams": []
        },
        {
            "id": 793,
            "email": "danni.gates@gmail.com",
            "username": "danni.gates",
            "name": "Danni",
            "surname": "Gates",
            "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon",
            "access_level": "5",
            "job_title": "Web Developer",
            "phone": "",
            "time_registered": "2019-12-06T16:37:08+01:00",
            "timezone": "Pacific/Midway",
            "status": "active",
            "teams": [
                {
                    "id": 2,
                    "name": "IT Department",
                    "position": 0
                }
            ]
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 2,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all members.

HTTP Request

GET https://blogin.co/api/rest/members

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort @id Sorting column. Available: id, name, surname, time_registered. See Sorting.
Example: GET https://blogin.co/api/rest/members?sort=@surname

Get a specific member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('members/793');
$member = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/members/793'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 793,
    "email": "danni.gates@gmail.com",
    "username": "danni.gates",
    "name": "Danni",
    "surname": "Gates",
    "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon",
    "access_level": "5",
    "job_title": "Web Developer",
    "phone": "",
    "time_registered": "2019-12-06T16:37:08+01:00",
    "timezone": "Pacific/Midway",
    "status": "active",
    "teams": [
        {
            "id": 2,
            "name": "IT Department",
            "position": 0
        }
    ]
}

This endpoint retrieves a specific member.

HTTP Request

GET https://blogin.co/api/rest/members/:id

URL Parameters

Parameter Description
:id The ID of the member to retrieve

Update a specific member

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;
  
  
  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->post('members/793', ['json' => [
    'email' => 'danni.gates@gmail.com',
    'username' => 'danni.gates',
    'name' => 'Danni',
    'surname' => 'Gates',
    'access_level' => 'Commenter',
    'job_title' => 'Web Developer',
    'phone' => '',
    'teams' => [
        [
            'id' => 2
        ],
    ]
  ]]);
  
curl --request POST 'https://blogin.co/api/rest/members/793' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer {key}' \
    --data-raw '{
        "email": "danni.gates@gmail.com",
        "username": "danni.gates",
        "name": "Danni",
        "surname": "Gates",
        "access_level": "Commenter",
        "job_title": "Web Developer",
        "phone": "",
        "teams": [
            {
                "id": 2
            }
        ]
    }'
    

Make sure to replace {key} with your API key.

Response:

{
      "id": 793,
      "email": "danni.gates@gmail.com",
      "username": "danni.gates",
      "name": "Danni",
      "surname": "Gates",
      "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon",
      "access_level": "5",
      "job_title": "Web Developer",
      "phone": "",
      "time_registered": "2019-12-06T16:37:08+01:00",
      "timezone": "Pacific/Midway",
      "teams": [
          {
              "id": 2,
              "name": "IT Department",
              "position": 0
          }
      ]
  }
  

This endpoint updates a specific member. A successful update answers 200.

Send only the fields you want to change. Every field you leave out keeps its current value.

Send null to clear a field. name, surname, job_title and phone accept null, which stores no value, and "", which stores an empty string. email, username and access_level refuse both with 400.

teams replaces the teams of the member. The member ends up in exactly the teams you send; [] or null removes every team. An omitted teams keeps the current teams. Teams managed by your SSO integration are never removed or added this way. To add one team without sending the whole list, call assign a team to the member. A team id of -1 is a 400 here.

The company owner is protected. These rules apply only when the target member is the owner, and a refusal is always 403:

HTTP Request

POST https://blogin.co/api/rest/members/:id

URL Parameters

Parameter Description
:id The ID of the member to update

Request body - JSON format

Parameter Description
email Member email address.
username Member username. Same characters as on create, otherwise 400. Omit the field to keep the stored username.
A username of up to 35 characters is stored exactly as sent. It must be unique in the workspace (letter case is ignored), otherwise 400. The member's own current username is accepted.
A longer username is shortened as on create: cut to 35 characters, given a suffix such as .4821 when the name is taken, and listed in meta.warnings.
409: another request took the same username at the same moment, or no free name was found for a shortened username (send a different username).
Older usernames: on any update, a stored username longer than 63 characters is shortened (normally to a unique name of at most 35 characters, else to 63), and an @ is replaced with . (with a suffix when that name is taken). The response returns the stored username.
name Member name. null clears it.
surname Member surname. null clears it.
access_level Member role: the name (Administrator, Reviewer, Writer, Commenter, Reader) or the level number that responses return (20, 15, 10, 5, 2). Any other value, "" included, is a 400. Omit it to keep the role. The role of the company owner cannot change through the API.
job_title Member job_title. null clears it.
phone Member phone. null clears it.
teams Array of objects, each with an id field, for the Teams of the member. The list replaces the current teams; [] or null removes them all. Example: [{"id": 123}]

Get posts created by a specific member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('members/33655/posts');
$posts = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/members/793/posts'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 3562,
            "title": "Welcome",
            "thumbnail_image": "",
            "author": {
                "id": 793,
                "name": "Danni Gates",
                "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
            },
            "published": true,
            "important": false,
            "wiki": false,
            "pinned": false,
            "approved": true,
            "has_published_poll": false,
            "date_published": "2020-03-02T09:47:50+01:00",
            "comments_disabled": false,
            "comments": 0,
            "votes_up": 0,
            "votes_down": 0,
            "categories": []
        }
    ],
    "meta": {
        "pagination": {
            "total": 1,
            "count": 1,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all posts created by a specific member.

HTTP Request

GET https://blogin.co/api/rest/members/:id/posts

URL Parameters

Parameter Description
:id The ID of the member to retrieve

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort -date_published Sorting column. Available: id, date_published. See Sorting.
Example: GET https://blogin.co/api/rest/members/:id/posts?sort=@date_published

Deactivate a specific member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('members/deactivate', ['json' => [
    'member_id' => 793
]]);
curl --location --request POST 'https://blogin.co/api/rest/members/deactivate'\
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw
  '{
    "member_id": 793
   }'

Make sure to replace {key} with your API key.

Response: 200 with the member as stored after the change, in the same format as Get a specific member (its status shows active or deactivated). A write-only key gets only {"id": 123}. On an error, 4xx or 5xx (see errors).

This endpoint helps you to deactivate a specific member.

HTTP Request

POST https://blogin.co/api/rest/members/deactivate

Request body - JSON format

Parameter Description
member_id The ID of the member to deactivate. mandatory

The company owner cannot be deactivated through the API, not even with the owner's own key.

Activate a specific member

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;
  
  
  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->post('members/activate', ['json' => [
      'member_id' => 793
  ]]);
  
curl --location --request POST 'https://blogin.co/api/rest/members/activate'\
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer {key}' \
    --data-raw
    '{
      "member_id": 793
     }'
  

Make sure to replace {key} with your API key.

Response: 200 with the member as stored after the change, in the same format as Get a specific member (its status shows active or deactivated). A write-only key gets only {"id": 123}. On an error, 4xx or 5xx (see errors).

This endpoint helps you to activate a specific member.

HTTP Request

POST https://blogin.co/api/rest/members/activate

Request body - JSON format

Parameter Description
member_id The ID of the member to activate. mandatory

Delete a specific member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('members/793');
curl --location --request DELETE 'https://blogin.co/api/rest/members/793'\
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This endpoint helps you to delete a specific member.

The delete is the same as a delete in the BlogIn web app. The posts and comments of the member stay. Their author changes to {"id": null, "name": "<name of the deleted member>", "avatar": null}. BlogIn does not send an email to the member. A member that is already deleted returns 404.

The delete is atomic. If it fails on the server, the API returns 500 and nothing changes: the member, their invitation and the author name on their posts and comments stay as they were. You can safely send the same request again. The retry returns 204, or 404 if the member was deleted in the meantime.

The company owner is protected. These rules apply only when the target member is the owner, and a refusal is always 403:

HTTP Request

DELETE https://blogin.co/api/rest/members/:id

URL Parameters

Parameter Description
:id The ID of the member to delete

Member teams

Member team properties

Every team list of a member (in a member object and in the responses of the member team routes below) is ordered by team position, then id.

Attribute Type Description
id int Unique identifier for the resource. read-only
name string Team name.
position float Sort position, used to custom sort the resource.
locked bool Whether or not the team is locked.
sso_managed bool Whether or not the team membership comes from your identity provider. read-only

Assign a team to the member

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('members/454/teams', ['json' => ['id' => 32]]);
$response = json_decode($response->getBody());
curl --request POST 'http://blogin.co/api/rest/members/454/teams' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {key}' \
--data-raw '{
    "id": 32
}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 4,
            "name": "Marketing",
            "position": 4,
            "locked": false,
            "sso_managed": false
        }
    ]
}

This endpoint helps you to assign the member to a team.

Status codes. 200, with the full team list of the member in the body. The request is idempotent: when the member is already in the team, nothing changes and the answer is the same 200 with the same list.

SSO-managed teams are read-only while SSO is on. The API refuses to change the membership of a team when both conditions hold: the team has sso_managed: true, and your company has an enabled SSO integration. The response is then 403 with the message Cannot modify membership of SSO-managed team, and you change the membership in your identity provider instead. A team marked sso_managed in a company whose SSO integration is disabled is not protected: the call succeeds.

HTTP Request

POST https://blogin.co/api/rest/members/:id/teams

URL Parameters

Parameter Description
:id The ID of the member.

Request body - JSON format

Parameter Description
id The ID of the Team. mandatory

Get all member teams

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('members/454/teams');
$teams = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/members/454/teams'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 4,
            "name": "Marketing",
            "position": 4,
            "locked": false,
            "sso_managed": false
        }
    ]
}

HTTP Request

GET https://blogin.co/api/rest/members/:id/teams

This endpoint retrieves all teams for member.

URL Parameters

Parameter Description
:id The ID of the member

Remove a member from a team

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$blogInApi->delete('members/454/teams/32');
curl --location --request DELETE 'https://blogin.co/api/rest/members/454/teams/32' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (200 OK, 4xx or 5xx for errors)

{
    "data": []
}

This endpoint removes a member from a team.

Status codes. 200, with the full team list of the member in the body. The request is idempotent: when the member is already not in the team, nothing changes and the answer is the same 200 with the same list.

SSO-managed teams are read-only while SSO is on. The API refuses to change the membership of a team when both conditions hold: the team has sso_managed: true, and your company has an enabled SSO integration. The response is then 403 with the message Cannot modify membership of SSO-managed team, and you change the membership in your identity provider instead. A team marked sso_managed in a company whose SSO integration is disabled is not protected: the call succeeds.

HTTP Request

DELETE https://blogin.co/api/rest/members/:memberId/teams/:teamId

URL Parameters

Parameter Description
memberId The ID of the member
teamId The ID of the team to delete

Posts

Post Properties

Attribute Type Description
id int Unique identifier of the resource.
title string Post title mandatory
thumbnail_image string Post thumbnail image. Empty string when the post has no image thumbnail. read-only list only
intro_text string Post intro text. read-only single post only
text string Post text (HTML). mandatory single post only
author object Author of the post: an object with an id field. See Post - Author properties
author.id is mandatory on create. On update, omit author to keep it, or send null to remove it.
A post without an author, or with a deleted author, returns {"id": null, "name": "Jane Doe", "avatar": null}. The name is the name of the deleted author, or "Unknown". Sending this object back changes nothing.
published bool Whether or not the post is published.
important bool Whether or not the post should be marked as important.
wiki bool Whether or not the post should be marked as wiki.
pinned bool Whether or not the post should be pinned.
comments_disabled bool Whether or not comments are disabled on the post.
notify bool Whether the post notifies its audience. Stored state: it is safe to send back, and on its own it never sends anything. notify says whether to notify; notify_all_users and teams say who.
notify_all_users bool The notification audience is every user of the company. When true, teams is inert for delivery.
visible_all_users bool Every user may read the post. Applies only when your company uses post visibility.
date_published date-time Post published date (ISO-8601 format).
comments int Number of comments. read-only
votes_up int Number of votes up (the exact number, with no upper limit). read-only
votes_down int Number of votes down (the exact number, with no upper limit). read-only
categories array Array containing category names OR category IDs. See Post - Categories properties
tags array List of tags.
teams array List of stored notification recipients. On create or update, this field is applied only when notify is true; otherwise the supplied value is ignored. See Post - Teams properties
visibility_teams array List of teams that can see this post. Works only with the Post visibility option turned on.
approved bool Whether or not the post is approved. Works only when approval of posts is required. Send 1 or 0 in a request; the response returns true or false.
has_published_poll bool Whether or not poll is published on the post. read-only
post_poll object Poll of the post, or null when the post has no poll. See Post Poll properties

Two response shapes. A list of posts and a single post do not return the same fields.

Response Endpoints Fields
Single post GET /posts/:id, POST /posts, POST /posts/:id All fields above except thumbnail_image, plus tags, teams and visibility_teams.
List of posts GET /posts, GET /members/:id/posts, GET /categories/:id/posts Adds thumbnail_image. Leaves out text and intro_text. Of the arrays, only categories is returned.

Post - Author properties

Attribute Type Description
id int Unique identifier for the resource.
name string Author name. read-only
avatar string Author avatar. read-only

Post - Categories properties

Attribute Type Description
id int Unique identifier for the resource.
name string Category name. read-only
position float Sort position, used to custom sort the resource. read-only

Post - Teams properties

Attribute Type Description
id int Unique identifier for the resource.
name string Team name. read-only
position float Sort position, used to custom sort the resource. read-only
locked bool Whether or not the team is locked. read-only

The teams and visibility_teams arrays of a post carry these four fields only. They do not carry sso_managed, unlike the Teams endpoints.

Post - Poll properties

Attribute Type Description
id int Unique identifier for the resource. read-only
question string Poll question. mandatory when you send post_poll.
type int Type of the poll, multiple (1), or single (2) answers. mandatory when you send post_poll.
published bool Whether the poll shows on the post. Optional. When you omit it, an existing poll keeps its state (a draft stays a draft), and a new poll is published. false stores a draft, which can be incomplete (empty question, fewer than two answers), as in the web editor. true publishes the poll; then a question and two answers are required.
answers array Array of the poll answers. mandatory when you send post_poll.
In a request, send each answer as an object with a text field, and send at least two answers that are not empty (a draft poll can send fewer). Answers are stored trimmed, and "0" is a valid answer.
A response returns all answers in the order they were saved. Each answer has id, poll_id, text, votes_count (the exact number of votes) and votes_percent.

A poll object carries these five fields only. The poll has no separate author field: the API records the author.id of the post as the member who published the poll.

votes_percent changes type with the data. An answer that has votes returns a string with two decimals, such as "33.33". An answer on a poll with no votes at all returns the number 0. Parse it as a number in both cases.

Create new post

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$post = [
    'title' => 'Welcome',
    'text' => '<p>Welcome, great to have you here.</p>',
    'published' => true,
    'date_published' => '2020-03-02T09:47:50+01:00',
    'wiki' => false,
    'important' => false,
    'pinned' => false,
    'approved' => 1,
    'notify' => true,
    'author' => [
        'id' => 793,
    ],
    'categories' => [
        [
            'id' => 125
        ],
        [
          'name' => 'News'
        ],
        [
          'name' => 'Updates'
        ]
    ],
    'teams' => [
        [
            'id' => -1   /* notify all teams */
        ]
    ],
    'visibility_teams' => [
        [
            'id' => 6
        ],
        [
            'id' => 9
        ]
    ],
    'tags' => [
        'Getting Started',
        'Report'
    ],
    'post_poll' => [
      'question' => 'Do you agree with the main point of this article?',
      'type' => 2,
      'answers' =>[
        [
            'text' => 'Yes'
        ],
        [
            'text' => 'No'
        ]
      ]
    ]
];

$response = $blogInApi->post('posts', ['json' => $post]);
curl --request POST 'https://blogin.co/api/rest/posts' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {key}' \
--data-raw '{
    "title": "Welcome",
    "text": "<p>👋 Welcome, great to have you here.</p>",
    "published": true,
    "date_published": "2020-03-02T09:47:51+01:00",
    "wiki": false,
    "important": false,
    "pinned": false,
    "notify": true,
    "author": {
        "id": 793
    },
    "categories": [
        {
            "id": 125
        },
        {
            "name": "News"
        },
        {
            "name": "Reports/Meetings"
        }
    ],
    "teams": [
        {
            "id": -1
        }
    ],
    "tags": ["Getting Started"],
    "approved": 1,
    "post_poll": {
      "question": "Do you agree with the main point of this article?",
      "type": 2,
      "answers": [
          {
              "text": "Yes"
          },
          {
              "text": "No"
          }
      ]
    }
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 3562,
    "title": "Welcome",
    "text": "<p>&eth;&#159;&#145;&#139; Welcome, great to have you here.</p>\n",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "published": true,
    "important": false,
    "wiki": false,
    "pinned": false,
    "approved": true,
    "has_published_poll": true,
    "date_published": "2020-03-02T09:47:50+01:00",
    "comments_disabled": false,
    "comments": 0,
    "votes_up": 0,
    "votes_down": 0,
    "post_poll": {
      "id": 123,
      "question": "Do you agree with the main point of this article?",
      "type": 2,
      "answers": [
        {
          "id": 6950,
          "poll_id": 123,
          "text": "Yes",
          "votes_count": 0,
          "votes_percent": 0
        },
        {
          "id": 6951,
          "poll_id": 123,
          "text": "No",
          "votes_count": 0,
          "votes_percent": 0
        }
      ]
    },
    "visibility_teams": [
    {
          "id": 6,
          "name": "Testers",
          "position": 2,
          "locked": false
      },
      {
      "id": 9,
      "name": "Journalists",
      "position": 2,
      "locked": false
  }
    ],
    "categories": [
        {
            "id": 125,
            "name": "Updates",
            "position": 2
        }
    ],
    "tags": [
        {
            "id": 24,
            "name": "Getting Started",
            "slug": "getting-started"
        }
    ],
    "teams": []
}

This API allows you to create a new post.

HTTP Request

POST https://blogin.co/api/rest/posts

Request body - JSON format

Parameter Description
title The title of the post. mandatory
text The text of the post, HTML format. mandatory
published Published flag (true/false). Default: false
date_published Post publication date and time in ISO-8601 format, with the time zone offset. Example: 2021-11-01T11:12:44+00:00. The API stores the value in the server time zone and returns it with the server offset, so it can look different but names the same moment. Default: now, when published is true.
wiki Wiki flag (true/false). Default: false
important Important flag (true/false). Default: false
pinned Pinned flag (true/false). Default: false
comments_disabled Comments disabled flag (true/false). Default: false
author Author of the post. (Object, id field is mandatory) The author must be an active, verified member with Writer access or higher; otherwise the request answers 400. mandatory
categories Array of objects with a Category id or name. See example. The API looks up an id first, then the name. Use "Parent/Child" to name a subcategory. An id is a JSON integer or a string of digits.
A wrong entry never rejects the post. The API skips an unknown category, a category of another workspace, and a locked category that the post does not already have. It lists each skipped entry in meta.warnings, for example "category id 99 not found, skipped" or "category \"News\" is locked, skipped". At most 20 warnings are listed, then one line counts the rest.
notify Whether users should be notified when this post is published (true/false). Must be true for teams to be applied. Default: false
teams Array of objects with the IDs of the Teams to notify when the post is published. Ignored unless notify is true. The legacy entry {"id": -1} means "notify all users"; use notify_all_users instead. Responses never return -1.
notify_all_users Notify every user of the company (true/false). Ignored unless notify is true. false together with {"id": -1} in teams is a 400. Default: false
visible_all_users WORKS ONLY WITH POST VISIBILITY Every user may read the post (true/false). false together with {"id": -1} in visibility_teams is a 400.
visibility_teams WORKS ONLY WITH POST VISIBILITY Array of objects with the IDs of the Teams that can see this post. The legacy entry {"id": -1} means "visible to all users"; use visible_all_users instead. Responses never return -1.
tags Array of tags of the post. A tag that cannot be saved does not reject the post: the API skips it and lists it in meta.warnings, for example "tag \"News\" could not be saved, skipped".
approved Used only when approval of posts is required. Otherwise, defaults to 1 (true).
post_poll Poll of the post (object). When supplied, include the question, type and at least two answers. An empty object or array returns 400.

Get all posts

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('posts');
$posts = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/posts'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 3562,
            "title": "Welcome",
            "thumbnail_image": "",
            "author": {
                "id": 793,
                "name": "Danni Gates",
                "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
            },
            "published": true,
            "important": false,
            "wiki": false,
            "pinned": false,
            "approved": true,
            "has_published_poll": true,
            "date_published": "2020-03-02T09:47:50+01:00",
            "comments_disabled": false,
            "comments": 0,
            "votes_up": 0,
            "votes_down": 0,
            "post_poll": {
              "id": 123,
              "question": "Do you agree with the main point of this article?",
              "type": 2,
              "answers": [
                {
                  "id": 6950,
                  "poll_id": 123,
                  "text": "Yes",
                  "votes_count": 0,
                  "votes_percent": 0
                },
                {
                  "id": 6951,
                  "poll_id": 123,
                  "text": "No",
                  "votes_count": 0,
                  "votes_percent": 0
                }
              ]
            },
            "categories": []
        }
    ],
    "meta": {
        "pagination": {
            "total": 1,
            "count": 1,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all posts.

HTTP Request

GET https://blogin.co/api/rest/posts

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting (pagination).
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort -date_published Sorting column. Available: id, date_published. See Sorting.
Example: GET https://blogin.co/api/rest/posts?sort=@date_published
Note: Pinned posts will always be returned first when sort option 'date_published' is used.
author Author ID. Limit result set to posts from specific author.

Get a specific post

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('posts/3562');
$post = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/posts/1'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 3562,
    "title": "Welcome",
    "text": "<p>&eth;&#159;&#145;&#139; Welcome, great to have you here.</p>\n",
    "intro_text": "<p>&eth;&#159;&#145;&#139; Welcome, great to have you here.</p>\n",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "published": true,
    "important": false,
    "wiki": false,
    "pinned": false,
    "approved": true,
    "has_published_poll": true,
    "date_published": "2020-03-02T09:47:50+01:00",
    "comments_disabled": false,
    "comments": 0,
    "votes_up": 0,
    "votes_down": 0,
    "post_poll": null,
    "visibility_teams": [],
    "categories": [],
    "tags": [
        {
            "id": 24,
            "name": "Getting Started",
            "slug": "getting-started"
        }
    ],
    "teams": []
}

This endpoint retrieves a specific post.

HTTP Request

GET https://blogin.co/api/rest/posts/:id

URL Parameters

Parameter Description
:id The ID of the post to retrieve

Update a post

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$post = [
    'title' => 'Welcome again',
    'text' => '<p>👋 Welcome, great to have you here again.</p>',
    'published' => true,
    'wiki' => false,
    'important' => false,
    'pinned' => true,
    'approved' => 1,
    'notify' => true,
    'author' => [
        'id' => 793,
    ],
    'categories' => [
        [
            'id' => 125
        ],
        [
          'name' => 'News'
        ],
        [
          'name' => 'Updates'
        ]
    ],
    'teams' => [
        [
            'id' => -1,      /* notify all teams */
        ]
    ],
    'visibility_teams' => [
        [
            'id' => 6
        ],
        [
            'id' => 9
        ]
    ],
    'tags' => [
        'Getting Started',
        'Report'
    ],
    'post_poll' =>  [
      'question' => 'Do you agree with the main point of this article?',
      'type' => 2,
      'answers' =>[
        [
            'text' => 'Yes'
        ],
        [
            'text' => 'No'
        ]
      ]
    ]
];

$response = $blogInApi->post('posts/3562', ['json' => $post]);
$post = json_decode($response->getBody());


curl --location --request POST 'https://blogin.co/api/rest/posts/3562' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "title": "Welcome again",
    "text": "<p>👋 Welcome, great to have you here again.</p>",
    "published": true,
    "wiki": false,
    "important": false,
    "pinned": true,
    "notify": true,
    "author": {
        "id": 793
    },
    "categories": [
        {
            "name": "News"
        },
        {
            "name": "Reports/Meetings"
        },
        {
            "id": 125
        }
    ],
    "teams": [
        {
            "id": -1
        }
    ],
    "tags": ["Getting Started"],
    "post_poll": {
        "question": "Do you agree with the main point of this article?",
        "type": 1,
        "answers": [
            {
                "text": "Yes"
            },
            {
                "text": "No"
            }
        ]
    }
  }'

Make sure to replace {key} with your API key.

Response:

{
    "id": 3562,
    "title": "Welcome again",
    "text": "Welcome, great to have you here again.</p>\n",
    "intro_text": "<p>&eth;&#159;&#145;&#139; Welcome, great to have you here.</p>\n",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "published": true,
    "important": false,
    "wiki": false,
    "pinned": true,
    "approved": true,
    "has_published_poll": true,
    "date_published": "2020-03-02T09:47:50+01:00",
    "comments_disabled": false,
    "comments": 0,
    "votes_up": 0,
    "votes_down": 0,
    "post_poll": {
      "id": 123,
      "question": "Do you agree with the main point of this article?",
      "type": 2,
      "answers": [
        {
          "id": 6950,
          "poll_id": 123,
          "text": "Yes",
          "votes_count": 0,
          "votes_percent": 0
        },
        {
          "id": 6951,
          "poll_id": 123,
          "text": "No",
          "votes_count": 0,
          "votes_percent": 0
        }
      ]
    },
    "visibility_teams": [
    {
          "id": 6,
          "name": "Testers",
          "position": 2,
          "locked": false
      },
      {
      "id": 9,
      "name": "Journalists",
      "position": 2,
      "locked": false
  }
    ],
    "categories": [
    {
        "id": 125,
            "name": "Updates",
            "position": 2
        }
    ],
    "tags": [
        {
            "id": 24,
            "name": "Getting Started",
            "slug": "getting-started"
        }
    ],
    "teams": []
}

This endpoint lets you make changes to a post.

An update is a partial update. Send only the fields you want to change; every field you leave out keeps its value. A successful update answers 200.

Notifications. notify is stored state, so sending it back unchanged, or sending true, never re-sends a post that users already saw. To notify the audience again about this update, send the write-only field renotify: true; it is never stored or returned. A post that becomes visible for the first time (a draft you publish, or an approval) always sends its notification. It reaches the stored teams, or every user, only when notify is on; with notify off, only mentioned users and followers are notified. The audience is always read from what is stored after the update, never from the request.

HTTP Request

POST https://blogin.co/api/rest/posts/:id

URL Parameters

Parameter Description
:id The ID of the post to update

Request body - JSON format

Parameter Description
title The title of the post. "" and null are refused.
text The text of the post, HTML format.
published Published flag (true/false). Omitted: unchanged.
wiki Wiki flag (true/false). Omitted: unchanged.
important Important flag (true/false). Omitted: unchanged.
pinned Pinned flag (true/false). Omitted: unchanged.
date_published Post published date (ISO-8601 format). Send the offset with the value; the API converts it to the time zone of the server before it stores it.
comments_disabled Comments disabled flag (true/false). Omitted: unchanged.
author Author of the post, an object with an id field. null removes the author. A new author must be an active, verified member with Writer access or higher; the current author can always be sent back unchanged.
categories Array of objects with a Category id or name, with the same lookup and skip rules as in Create new post. Omit to keep the current categories; send [] or null to clear them. When no entry in the list is found, the API keeps the current categories and says so in meta.warnings.
notify Whether the post notifies its audience (true/false). Stored state: on a post that users already saw it sends nothing. Must be on for a populated teams or notify_all_users: true to be applied.
renotify Write-only: never stored, never returned. true notifies the stored audience again about this update, also when notify is false, as the web editor does. The stored audience is the stored teams, or every user when notify_all_users is stored true, including recipients kept from when notify was on. It does not change notify.
notify_all_users Notify every user of the company (true/false). true is applied only when notify is on; false always clears it. false with {"id": -1} in teams is a 400.
visible_all_users WORKS ONLY WITH POST VISIBILITY FEATURE Every user may read the post (true/false). Ignored when your company does not use post visibility. false with {"id": -1} in visibility_teams is a 400.
teams Array of objects with the IDs of the Teams to notify. Replaces the stored recipients when notify is on, and is ignored when it is off. [] or null clears them in both cases. The legacy entry {"id": -1} means "notify all users"; responses never return -1.
visibility_teams WORKS ONLY WITH POST VISIBILITY FEATURE Array of objects with the IDs of the Teams that can see this post. [] or null clears them. The legacy entry {"id": -1} means "visible to all users"; responses never return -1.
tags Array of tag names, or tag objects with a name (as a response returns them). Replaces the stored tags; [] or null clears them. A tag that cannot be saved is skipped and listed in meta.warnings, for example "tag \"News\" could not be saved, skipped". When no tag in the list can be saved, the API keeps the current tags and says so in meta.warnings.
approved Used only when approval of posts is required. Otherwise, defaults to 1 (true).
post_poll Poll of the post (object). Omit to keep it, send null to delete it, or send a complete object to create or update it. An empty object or array returns 400; changing a poll with votes returns 409.

Delete a post

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('posts/3562');
curl --location --request DELETE 'https://blogin.co/api/rest/posts/3562' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This API allows you delete a post.

HTTP Request

DELETE https://blogin.co/api/rest/posts/:id

URL Parameters

Parameter Description
:id The ID of the post to delete

Post comments

Post comment properties

Attribute Type Description
id int Unique identifier for the resource. read-only
parent int The ID of the parent comment, or null for a top-level comment. 0 is no longer returned.
text string Comment text mandatory
author object Author of the comment: an object with an id field. See Post Comments - Author properties
author.id is mandatory on create. On update, omit author to keep it, or send null to remove it.
A comment without an author, or with a deleted author, returns "id": null, the name of the deleted author (or "Unknown") and "avatar": null. Sending this object back changes nothing. A top-level comment returns parent: null.
created_at date-time Comment creation date (ISO-8601 format). read-only
approved_at date-time Date the comment was approved (ISO-8601 format), or null when it is unapproved. read-only
votes_up int Number of votes up. read-only
votes_down int Number of votes down. read-only
approved bool Whether or not the comment is approved. Used only when approval of comments is required. Otherwise it defaults to true. Send 1 or 0 in a request; the response returns true or false.

You can include base64 encoded images in the comment text, the same way as in a post text. The images are extracted, decoded and saved as files. The same formats, limits and status codes apply.

Post comment - Author properties

Attribute Type Description
id int Unique identifier for the resource.
name string Author name. read-only
avatar string Author avatar. read-only

Add new post comment

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$comment = [
    'parent' => null,
    'text' => '<p>👋 Welcome, great to have you here.</p>',
    'author' => [
        'id' => 793,
    ],
    'approved' => 1,
];

$response = $blogInApi->post('posts/3562/comments', ['json' => $comment]);
$response = json_decode($response->getBody());
curl --request POST 'http://blogin.co/api/rest/posts/3562/comments' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {key}' \
--data-raw '{
    "parent": null,
    "text": "<p>👋 Welcome, great to have you here.</p>",
    "author": {
        "id": 793
    }
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1487,
    "parent": null,
    "text": "<p>👋 Welcome, great to have you here.</p>",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "approved": true,
    "created_at": "2020-01-17T14:30:51+01:00",
    "approved_at": "2020-01-17T14:31:09+01:00",
    "votes_up": 0,
    "votes_down": 0
}

This endpoint helps you to create a new comment.

HTTP Request

POST https://blogin.co/api/rest/posts/:id/comments

URL Parameters

Parameter Description
:id The ID of the post.

Comments disabled. When the post has comments_disabled: true, the request answers 403 with the message Comments are disabled for this post. and no comment is created, also no reply. Existing comments of the post can still be updated and deleted.

Post not published. When the post is a draft (published: false), waits for approval (approved: false), or is scheduled (date_published in the future), the request answers 403 with the message Comments are allowed only on published and approved posts. and no comment is created, also no reply. Existing comments of the post can still be updated and deleted.

Request body - JSON format

Parameter Description
parent The ID of the parent comment (if this comment is a reply).
text The text of the comment, HTML format. mandatory
author The object containing the ID of the author of the comment. The author must be an active, verified member with Commenter access or higher; otherwise the request answers 400. mandatory
approved Used only when approval of comments is required. If omitted, the comment is approved (1/true).

Get all post comments

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('posts/3562/comments');
$comments = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/posts/3562/comments'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 1485,
            "parent": null,
            "text": "You there?",
            "author": {
                "id": 797,
                "name": "Ariana Clay",
                "avatar": "https://secure.gravatar.com/avatar/a4d5b21c4e7eeb3bd2e8a9d278772ea9?s=90&d=identicon"
            },
            "approved": true,
            "created_at":  "2020-01-15T11:18:50+01:00",
            "approved_at": "2020-01-17T14:31:09+01:00",
            "votes_up": 1,
            "votes_down": 0
        },
        {
            "id": 1487,
            "parent": null,
            "text": "<p>👋 Welcome, great to have you here.</p>",
            "author": {
                "id": 793,
                "name": "Danni Gates",
                "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
            },
            "approved": true,
            "created_at": "2020-01-17T14:30:51+01:00",
            "approved_at": "2020-01-17T14:31:09+01:00",
            "votes_up": 2,
            "votes_down": 0
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 2,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all comments for post.

Approved comments only. A comment that waits for approval is not in the response, and it is not in the meta.pagination counts either. This matters when your company requires approval of comments: the comments count on the post can be higher than the number of comments you get here.

HTTP Request

GET https://blogin.co/api/rest/posts/:id/comments

URL Parameters

Parameter Description
:id The ID of the post to retrieve

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting (pagination).
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort @created_at Sorting column. Available: id, created_at. See Sorting.
Example: GET https://blogin.co/api/rest/posts/:id/comments?sort=-id

Update a post comment

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('posts/3562/comments/1487', ['json' => [
    'text' => '<p>👋 Welcome, great to have you here again.</p>',
    'author' => [
        'id' => 793,
    ],
    'approved' => 1,
]]);
curl --location --request POST 'https://blogin.co/api/rest/posts/3562/comments/1487' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "text": "<p>👋 Welcome, great to have you here again.</p>",
    "author": {
        "id": 793
    }
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1487,
    "parent": null,
    "text": "<p>👋 Welcome, great to have you here again.</p>",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "approved": true,
    "created_at": "2020-01-17T14:30:51+01:00",
    "approved_at": "2020-01-17T14:31:09+01:00",
    "votes_up": 2,
    "votes_down": 0
}

This endpoint lets you make changes to a post comment.

HTTP Request

POST https://blogin.co/api/rest/posts/:postId/comments/:commentId

URL Parameters

Parameter Description
:postId The ID of the parent post
:commentId The ID of the comment to update

Request body - JSON format

Parameter Description
text The text of the comment. Omitted: unchanged. "" and null are refused.
author The object containing the ID of the comment author. Omitted: unchanged. null removes the author. A new author must be an active, verified member with Commenter access or higher; the current author can always be sent back unchanged.
approved Used only when approval of comments is required. Otherwise, defaults to 1 (true).

Delete a post comment

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('posts/3562/comments/1487');
curl --location --request DELETE 'https://blogin.co/api/rest/posts/3562/comments/1487' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This endpoint helps you delete a post comment.

HTTP Request

DELETE https://blogin.co/api/rest/posts/:postId/comments/:commentId

URL Parameters

Parameter Description
:postId The ID of the parent post
:commentId The ID of the comment to delete

Pages

Page properties

Attribute Type Description
id int Unique identifier for the resource. read-only
title string Page title. mandatory
text string Page text. mandatory
author object Author of the page: an object with an id field. See Page - Author properties
author.id is mandatory on create. On update, null removes the author. A page without an author, or with a deleted author, returns {"id": null, "name": "Unknown", "avatar": null}. Sending this object back changes nothing.
published bool Whether or not the page is published.
position float Sort position, used to custom sort the resource.

Page - Author properties

Attribute Type Description
id int Unique identifier for the resource.
name string Author name. read-only
avatar string Author avatar. read-only

Create new page

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('pages', ['json' => [
    'title' => 'Welcome',
    'text' => '<p>👋 Welcome, great to have you here.</p>',
    'author' => [
        'id' => 793,
    ],
    'published' => true,
    'position' => 4
]]);
curl --request POST 'https://blogin.co/api/rest/pages' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "title": "Welcome",
    "text": "<p>👋 Welcome, great to have you here.</p>",
    "author": {
        "id": 793
    },
    "published": true,
    "position": 4
  }'

Make sure to replace {key} with your API key.

Response:

{
    "id": 227,
    "title": "Welcome",
    "text": "<p><img class=\"emojione\" alt=\"👋\" src=\"emojione/assets/png/1F44B.png\" title=\":wave:\"/> Welcome, great to have you here.</p>",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "position": 4
}

This endpoint helps you to create a new page.

HTTP Request

POST https://blogin.co/api/rest/pages

Request body - JSON format

Parameter Description
title The title of the page. mandatory
text Page text in HTML format. Page text does not support base64 data URIs: a data URI in a src, href, srcset or poster attribute, or in the data attribute of an <object>, answers 415. This also applies inside a <template> element or an <iframe srcdoc> value. mandatory
author The object containing the ID of the author of the page. The author must be an active, verified member with Writer access or higher; otherwise the request answers 400. mandatory
published Published flag (true/false). Default: false. An omitted value stores the page as unpublished, and GET /pages does not return it.
position Sort position (float), from -1000000000 to 1000000000; any other value answers 400. Omitted or null: the page goes to the end. 0 is a valid position.

Get all pages

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('pages');
$pages = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/pages'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 227,
            "title": "Welcome",
            "author": {
                "id": 793,
                "name": "Danni Gates",
                "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
            },
            "position": 4
        }
    ],
    "meta": {
        "pagination": {
            "total": 1,
            "count": 1,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 0,
            "links": {}
        }
    }
}

This endpoint retrieves all pages.

Published pages only. An unpublished page is not in the response and not in the meta.pagination counts. To read one, request it by id with GET /pages/:id.

HTTP Request

GET https://blogin.co/api/rest/pages

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting (pagination).
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort @position Sorting column. Available: id, position. See Sorting.
Example: GET https://blogin.co/api/rest/pages?sort=-position

Get a specific page

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('pages/227');
$post = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/pages/227'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 228,
    "title": "Welcome",
    "text": "<p>👋 Welcome, great to have you here.</p>",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "position": 36
}

This endpoint retrieves a specific page.

HTTP Request

GET https://blogin.co/api/rest/pages/:id

URL Parameters

Parameter Description
:id The ID of the page to retrieve

Update a page

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('pages/227', ['json' => [
    'title' => 'Welcome again',
    'text' => '<p>👋 Welcome, great to have you here again.</p>',
    'author' => [
        'id' => 793,
    ],
    'published' => true,
    'position' => 72
]]);
curl --location --request POST 'https://blogin.co/api/rest/pages/1' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "title": "Welcome again",
    "text": "<p>👋 Welcome, great to have you here again.</p>",
    "author": {
        "id": 793
    },
    "published": true,
    "position": 72
  }'

Make sure to replace {key} with your API key.

Response:

{
    "id": 228,
    "title": "Welcome again",
    "text": "<p>👋 Welcome, great to have you here again.</p>",
    "author": {
        "id": 793,
        "name": "Danni Gates",
        "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
    },
    "position": 72
}

This endpoint lets you make changes to a page. A successful update answers 200.

The update is a partial update: send only the fields you want to change. An omitted position leaves the page where it is; null moves it to the end; 0 is stored as 0.

HTTP Request

POST https://blogin.co/api/rest/pages/:id

URL Parameters

Parameter Description
:id The ID of the page to update

Request body - JSON format

Parameter Description
title The title of the page. "" and null are refused.
text Page text in HTML format. Data URIs answer 415, as in Create new page.
author The object containing the ID of the author of the page. null removes the author. A new author must be an active, verified member with Writer access or higher; the current author can always be sent back unchanged.
published Published flag (true/false).
position Sort position, used to custom sort the resource (float). The value must be a number from -1000000000 to 1000000000; any other value answers 400.

Delete a page

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('pages/227');
curl --location --request DELETE 'https://blogin.co/api/rest/pages/227' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This endpoint helps you delete a page. The page moves to the trash. After that, the API treats it as not found: it is left out of GET /pages and search, and a read, update or delete of its id answers 404.

HTTP Request

DELETE https://blogin.co/api/rest/pages/:id

URL Parameters

Parameter Description
:id The ID of the page to delete

Categories

Category properties

Attribute Type Description
id int Unique identifier for the resource. read-only
parent int The ID for the parent of the resource, or null for a root category. 0 is no longer returned.
name string Category name. mandatory
position float Sort position, used to custom sort the resource.
locked bool Flag, if the category is locked or not. Default is false

Create new category

<?php
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('categories', ['json' => [
    'parent' => null,
    'name' => 'New name',
    'position' => 3,
    'locked' => false
]]);
curl --location --request POST 'https://blogin.co/api/rest/categories' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "parent": null,
    "name": "New name",
    "position": 3,
    "locked": false
  }'

Make sure to replace {key} with your API key.

Response:

{
    "id": 128,
    "parent": null,
    "name": "New name",
    "position": 3,
    "locked": false
}

This API endpoint allows you to create a new category.

HTTP Request

POST https://blogin.co/api/rest/categories

Request body - JSON format

Parameter Description
parent The ID of the parent category (int).
name The name of the category. mandatory
position Position of the category (float), from -1000000000 to 1000000000; any other value answers 400. Omitted or null: the category goes to the end. 0 is a valid position.
locked The flag if the category is locked or not (bool).

Get all categories

<?php
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('categories');
$categories = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/categories'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 1769,
            "parent": null,
            "name": "Economics & Management",
            "position": 1,
            "locked": false
        },
        {
            "id": 1777,
            "parent": null,
            "name": "Announcement",
            "position": 2,
            "locked": false
        },
        {
            "id": 1778,
            "parent": 1769,
            "name": "Economics",
            "position": 1,
            "locked": false
        },
        {
            "id": 1779,
            "parent": 1769,
            "name": "Management",
            "position": 2,
            "locked": true
        }
    ],
    "meta": {
        "pagination": {
            "total": 4,
            "count": 4,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all categories.

HTTP Request

GET https://blogin.co/api/rest/categories

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort @position Sorting column. Available: id, position. See Sorting.
Example: GET https://blogin.co/api/rest/categories?sort=-position

Get a specific category

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('categories/1');
$category = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/categories/1774'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1769,
    "parent": null,
    "name": "Economics & Management",
    "position": 1,
    "locked": false
}

This endpoint retrieves a specific category.

HTTP Request

GET https://blogin.co/api/rest/categories/:id

URL Parameters

Parameter Description
:id The ID of the category to retrieve

Get posts from a category

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;
  
  
  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->get('categories/1774/posts');
  $posts = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/categories/1774/posts'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "data": [
          {
              "id": 3562,
              "title": "Welcome",
              "thumbnail_image": "",
              "author": {
                  "id": 793,
                  "name": "Danni Gates",
                  "avatar": "https://secure.gravatar.com/avatar/d0f3ff35d9639d780e47ccd7dbad144d?s=90&d=identicon"
              },
              "published": true,
              "important": false,
              "wiki": false,
              "pinned": false,
              "approved": true,
              "has_published_poll": true,
              "date_published": "2020-03-02T09:47:50+01:00",
              "comments_disabled": false,
              "comments": 0,
              "votes_up": 0,
              "votes_down": 0,
              "categories": []
          }
      ],
      "meta": {
          "pagination": {
              "total": 1,
              "count": 1,
              "per_page": 10,
              "current_page": 1,
              "total_pages": 1,
              "links": {}
          }
      }
  }
  

This endpoint retrieves all posts from a specific category. Each post uses the list response shape. See Post Properties.

HTTP Request

GET https://blogin.co/api/rest/categories/:id/posts

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort -date_published Sorting column. Available: id, date_published. See Sorting.
Note: Pinned posts are always returned first when sort option date_published is used.

Get followers for a category

<?php

    use GuzzleHttp\Client;
    use GuzzleHttp\RequestOptions;
    
    
    $blogInApi = new Client([
        'base_uri' => 'https://blogin.co/api/rest/',
        RequestOptions::HEADERS => [
            'Accept' => 'application/json',
            'Authorization' => 'Bearer {key}',
        ],
    ]);
    
    $response = $blogInApi->get('categories/1774/followers');
    $posts = json_decode($response->getBody());
    
curl 'https://blogin.co/api/rest/categories/1774/followers'
      -H 'Authorization: Bearer {key}'
    

Make sure to replace {key} with your API key.

Response:

{
        "data": [
            {
            "id": 797,
            "email": "arianna@example.com",
            "username": "ariana.clay",
            "name": "Ariana",
            "surname": "Clay",
            "avatar": "https://secure.gravatar.com/avatar/a4d5b21c4e7eeb3bd2e8a9d278772ea9?s=90&d=identicon",
            "access_level": "2",
            "job_title": "Engineer",
            "phone": "",
            "time_registered": "2019-12-13T12:46:48+01:00",
            "timezone": "Pacific/Midway"
        }
        ],
        "meta": {
            "pagination": {
                "total": 1,
                "count": 1,
                "per_page": 10,
                "current_page": 1,
                "total_pages": 1,
                "links": {}
            }
        }
    }
    

This endpoint retrieves all followers from a specific category.

HTTP Request

GET https://blogin.co/api/rest/categories/:id/followers

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort id Sorting column. Available: id, name, surname, time_registered. See Sorting.

A follower is returned as a reduced member object. It carries every Member property except status and teams. Deleted and deactivated members are not returned.

Get categories of a post

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;


  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);

  $response = $blogInApi->get('posts/3562/categories');
  $categories = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/posts/:id/categories'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "data": [
          {
              "id": 1774,
              "parent": null,
              "name": "Company news",
              "locked": false,
              "position": 3
          }
      ]
  }
  

This endpoint retrieves all categories of a specific post. The response is not paginated, so it carries no meta object.

HTTP Request

GET https://blogin.co/api/rest/posts/:id/categories

URL Parameters

Parameter Description
:id The ID of the post

Update a category

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('categories/1', ['json' => [
    'parent' => null,
    'name' => 'New name',
    'position' => 0,
    'locked' => 0,
]]);
curl --location --request POST 'https://blogin.co/api/rest/categories/1' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "parent": null,
    "name": "New name",
    "position": 0,
    "locked": false
  }'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1,
    "parent": null,
    "name": "New name",
    "position": 0,
    "locked": false
}

This endpoint lets you make changes to a category. Omitting parent keeps the current parent; send parent: null to make the category a root category.

HTTP Request

POST https://blogin.co/api/rest/categories/:id

URL Parameters

Parameter Description
:id The ID of the category to update

Request body - JSON format

Parameter Description
parent ID of the parent category. Omitted: unchanged. null makes the category a root category. Categories have two levels, so the parent must be a root category, and a category that has subcategories cannot get a parent (400, nothing changes). The current parent can be sent back unchanged.
name The name of the category. Omitted: unchanged.
position Position of the category, from -1000000000 to 1000000000; any other value answers 400. Omitted: unchanged. null moves it to the end. 0 and decimals such as 2.5 are stored as sent.
locked The flag which represents if the category is locked or not.

Delete a category

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('categories/1');
curl --location --request DELETE 'https://blogin.co/api/rest/categories/1' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This endpoint helps you delete a category.

HTTP Request

DELETE https://blogin.co/api/rest/categories/:id

URL Parameters

Parameter Description
:id The ID of the category to delete

Tags

Tag properties

Attribute Type Description
id int Unique identifier for the resource. read-only
name string Tag name. read-only
slug string An alphanumeric identifier for the resource unique to its type. read-only
count int The number of times this tag has been used. read-only

Get all tags

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('tags');
$tags = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/tags'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 8,
            "name": "growth report",
            "slug": "growth-report",
            "count": 8
        },
        {
            "id": 9,
            "name": "internal communication",
            "slug": "internal-communication",
            "count": 5
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 2,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint retrieves all tags.

HTTP Request

GET https://blogin.co/api/rest/tags

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort -count Sorting column. Available: id, name, count. See Sorting.
Example: GET https://blogin.co/api/rest/tags?sort=@count

Get post tags

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;
  
  
  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->get('posts/3562/tags');
  $tags = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/posts/3562/tags'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "data": [
          {
              "id": 8,
              "name": "growth report",
              "slug": "growth-report",
              "count": 8
          },
          {
              "id": 9,
              "name": "internal communication",
              "slug": "internal-communication",
              "count": 5
          }
      ]
  }
  

This endpoint retrieves all tags of a specific post.

HTTP Request

GET https://blogin.co/api/rest/posts/:id/tags

Get a specific tag

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('tags/8');
$tag = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/tags/8'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 8,
    "name": "growth report",
    "slug": "growth-report",
    "count": 8
}

This endpoint retrieves a specific tag.

HTTP Request

GET https://blogin.co/api/rest/tags/:id

URL Parameters

Parameter Description
:id The ID of the tag to retrieve

Teams

Teams properties

Attribute Type Description
id int Unique identifier for the resource. read-only
name string Team name. mandatory
position float Sort position, used to custom sort the resource.
locked bool Flag for locked, if the team is locked or not.
sso_managed bool Whether or not the team membership comes from your identity provider. read-only

Create new team

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('teams', ['json' => [
    'name' => 'New team',
    'position' => 3,
    'locked' => false
]]);
curl --location --request POST 'https://blogin.co/api/rest/teams' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "name": "New team",
    "position": 3,
    "locked": false
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1,
    "name": "New team",
    "position": 3,
    "locked": false,
    "sso_managed": false
}

This API allows you to create a new team.

HTTP Request

POST https://blogin.co/api/rest/teams

Request body - JSON format

Parameter Description
name The name of the team. mandatory
position Position of the team (float), from -1000000000 to 1000000000; any other value answers 400. Omitted or null: the team goes to the end. 0 is a valid position.
locked The locked team flag (bool).

Get all teams

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('teams');
$teams = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/teams'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "id": 2,
            "name": "IT Department",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 39,
            "name": "[A][Z] Web developer",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 40,
            "name": "[A] Technical sales [NEW]",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 27,
            "name": "Business analyst",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 28,
            "name": "Software engineer",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 31,
            "name": "Technical support",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 33,
            "name": "Network engineer",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 36,
            "name": "Network engineer",
            "position": 0,
            "locked": true,
            "sso_managed": false
        },
        {
            "id": 3,
            "name": "Network engineer",
            "position": 0,
            "locked": false,
            "sso_managed": false
        },
        {
            "id": 38,
            "name": "[A] Software tester",
            "position": 0,
            "locked": true,
            "sso_managed": false
        }
    ],
    "meta": {
        "pagination": {
            "total": 13,
            "count": 10,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 2,
            "links": {
                "next": "https://blogin.co/api/rest/teams?page=2"
            }
        }
    }
}

This endpoint retrieves all teams.

HTTP Request

GET https://blogin.co/api/rest/teams

Query Parameters

Parameter Default Description
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
sort @position Sorting column. Available: id, position. See Sorting.
Example: GET https://blogin.co/api/rest/teams?sort=-position

Get a specific team

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('teams/38');
$team = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/teams/38'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 38,
    "name": "[A] Software tester",
    "position": 0,
    "locked": false,
    "sso_managed": false
}

This endpoint retrieves a specific team.

HTTP Request

GET https://blogin.co/api/rest/teams/:id

URL Parameters

Parameter Description
:id The ID of the team to retrieve

Update a team

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->post('teams/1', ['json' => [
    'name' => 'new team name',
    'position' => 0
]]);
curl --location --request POST 'https://blogin.co/api/rest/teams/1' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}' \
  --data-raw '{
    "name": "new team name",
    "position": 0
}'

Make sure to replace {key} with your API key.

Response:

{
    "id": 1,
    "name": "new team name 1",
    "position": 0,
    "locked": false,
    "sso_managed": false
}

This endpoint lets you make changes to a team.

HTTP Request

POST https://blogin.co/api/rest/teams/:id

URL Parameters

Parameter Description
:id The ID of the team to update

Request body - JSON format

Parameter Description
name The name of the team. Omitted: unchanged.
position Position of the team (sort order), from -1000000000 to 1000000000; any other value answers 400. Omitted: unchanged. null moves it to the end. 0 and decimals such as 2.5 are stored as sent.
locked The locked team flag.

Delete a team

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->delete('teams/1');
curl --location --request DELETE 'https://blogin.co/api/rest/teams/1' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response: Check HTTP response status code (204 No Content with no body, 4xx or 5xx for errors)

This endpoint helps you delete a team.

HTTP Request

DELETE https://blogin.co/api/rest/teams/:id

URL Parameters

Parameter Description
:id The ID of the team to delete

Search

Search properties

Attribute Type Description
resourceType string The type of the hit: post or page.
id int Unique identifier for the resource.
title string Resource title.
author object Author of the post or page. See Search - Author properties
date_published date-time Post published date (ISO-8601 format). Always null when resourceType is page.

Search - Author properties

Attribute Type Description
id int Unique identifier for the resource.
name string Author name.
avatar string Author avatar.

Search

<?php

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;


$blogInApi = new Client([
    'base_uri' => 'https://blogin.co/api/rest/',
    RequestOptions::HEADERS => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer {key}',
    ],
]);

$response = $blogInApi->get('search', ['query' => ['terms' => 'blogin']]);
$items = json_decode($response->getBody());
curl 'https://blogin.co/api/rest/search?terms=blogin'
  -H 'Authorization: Bearer {key}'

Make sure to replace {key} with your API key.

Response:

{
    "data": [
        {
            "resourceType": "post",
            "id": "787",
            "title": "test post #1",
            "author": {
                "id": 1,
                "name": "Jerry Ramos",
                "avatar": "https://secure.gravatar.com/avatar/f0e25c8dac1b38a771abba6f94bd613e?s=90&d=identicon"
            }
        },
        {
            "resourceType": "post",
            "id": "816",
            "title": "test post #2",
            "author": {
                "id": 1,
                "name": "Jerry Ramos",
                "avatar": "https://secure.gravatar.com/avatar/f0e25c8dac1b38a771abba6f94bd613e?s=90&d=identicon"
            }
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 2,
            "per_page": 10,
            "current_page": 1,
            "total_pages": 1,
            "links": {}
        }
    }
}

This endpoint will return items for given terms.

HTTP Request

GET https://blogin.co/api/rest/search

Query Parameters

Parameter Default Description
terms - The text to search for. mandatory, at most 255 characters; otherwise the request fails validation (400). Words are separated by spaces. Only the first 10 different words are used; the API ignores the rest and adds a meta.warnings entry, for example "terms has 12 different words; only the first 10 are used, the rest are ignored".
A post matches when any word is in its title, text, author name or (with comments) comment text, or when the text or a word is one of its tags. A word of 2 characters or less matches posts only through tags.
Pages have no tags. A page search ignores each word of 2 bytes or less in UTF-8, so such a word matches no page. A word of 1 or 2 characters that needs 3 or more bytes, for example 猫, is still searched in pages.
% and _ match only themselves; they are not wildcards.
A word with &, <, >, " or ' also matches its HTML-encoded form in titles, text and comment text. For example, R&D also finds post text that stores R&amp;D.
page 1 The page number that the client is requesting.
limit 10 The number of resources to return per-page. Min. 1, max. 100. A value outside this range fails validation.
comments false Search for posts in the comments text. Accepts true, false, 1 or 0.
pages false Include pages in search. Accepts true, false, 1 or 0.
sort -date_published Sorting column. Available: date_published. See Sorting.

The result lists the matching posts in the sort order first. When pages is true, the matching pages follow the posts, ordered by id. meta.pagination.total counts both.

Usage stats

This endpoint retrieves usage stats data for a specific period.

Rules for every stats endpoint. Each parameter takes one value. start_date must not be later than end_date, and the period must not be longer than 731 days (about two years). A date that cannot be read, a date that does not exist (for example 2026-02-31), and a reversed or too long period answer 400. On the paginated stats endpoints, a limit or page that is not an integer, and a page too large to compute, also answer 400. A sort column without a prefix sorts ascending. A list with no rows in the period is still an object with an empty list: "posts": {"data": []} or "members": {"data": []}.

Summary stats

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;

  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);

  $response = $blogInApi->get('stats');
  $stats = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/stats'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "posts_count": 42,
      "posts_per_week": 9.8,
      "comments_count": 128,
      "comments_per_week": 29.86,
      "engaged_users_count": 57,
      "engaged_users_percent": 63.33,
      "new_members_count": 4,
      "post_views_count": 1863,
      "post_votes_up_count": 211,
      "post_votes_down_count": 7
  }
  

This endpoint retrieves the summary usage stats of the company for a period. The response is a plain object. It is not paginated and it has no data key.

HTTP Request

GET https://blogin.co/api/rest/stats

Query Parameters

Parameter Default Description
start_date 30 days ago Start date (ISO-8601 format) Example: 2020-01-30.
end_date today End date (ISO-8601 format). Example: 2020-12-31T23:59:59

Response fields

Field Description
posts_countPublished posts in the period.
posts_per_weekAverage posts per week in the period.
comments_countComments on approved posts in the period. Posts in the trash are not counted.
comments_per_weekAverage comments per week in the period.
engaged_users_countMembers who were active at least once in the period.
engaged_users_percentEngaged members as a percent of all active members.
new_members_countMembers who registered in the period.
post_views_countViews of approved posts in the period. Posts in the trash are not counted.
post_votes_up_countUp votes on approved posts in the period. Posts in the trash are not counted.
post_votes_down_countDown votes on approved posts in the period. Posts in the trash are not counted.

Posts stats

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;

  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->get('stats/posts');
  $posts = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/stats/posts'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "posts_count": 81,
      "posts_per_week": 0.75,
      "comments_count": 25,
      "comments_per_week": 0.25,
      "engaged_users_count": 21,
      "engaged_users_percent": 86,
      "new_members_count": 33,
      "post_views_count": 3194,
      "post_votes_up_count": 15,
      "post_votes_down_count": 7,
      "posts": {
          "data": [
              {
                  "id": "787",
                  "title": "Example post",
                  "slug": "example-post",
                  "author_id": "123",
                  "author_name": "John Doe",
                  "date_published": "2020-03-02T09:47:50+01:00",
                  "post_views": "692",
                  "upVoteNum": "15",
                  "downVoteNum": "7",
                  "comments": "28",
                  "views": [
                      "John Doe",
                      "Jane Doe"
                  ]
              },
              {
                  "id": "967",
                  "title": "Welcome",
                  "slug": "welcome",
                  "author_id": "123",
                  "author_name": "John Doe",
                  "date_published": "2020-03-02T09:47:50+01:00",
                  "post_views": "986",
                  "upVoteNum": "21",
                  "downVoteNum": "3",
                  "comments": "52",
                  "views": [
                      "John Doe"
                  ]
              }
          ],
          "meta": {
              "pagination": {
                  "total": 1,
                  "count": 1,
                  "per_page": 10,
                  "current_page": 1,
                  "total_pages": 1,
                  "links": {}
              }
          }
      }
  }
  

This endpoint retrieves posts stats.

HTTP Request

GET https://blogin.co/api/rest/stats/posts

Query Parameters

Parameter Default Description
start_date 30 days ago Start date (ISO-8601 format) Example: 2020-01-30.
end_date today End date (ISO-8601 format). Example: 2020-12-31T23:59:59
page 1 The page number that the client is requesting (pagination).
limit 10 The number of resources to return per-page. Min. 1: a lower value answers 400. Values above 100 are reduced to 100.
sort -date_published Sorting column. Available: title, date_published, post_views, comments, upVoteNum, downVoteNum. See Sorting.
Example: GET https://blogin.co/api/rest/stats/posts?sort=@date_published

Members stats

<?php

  use GuzzleHttp\Client;
  use GuzzleHttp\RequestOptions;

  $blogInApi = new Client([
      'base_uri' => 'https://blogin.co/api/rest/',
      RequestOptions::HEADERS => [
          'Accept' => 'application/json',
          'Authorization' => 'Bearer {key}',
      ],
  ]);
  
  $response = $blogInApi->get('stats/members');
  $members = json_decode($response->getBody());
  
curl 'https://blogin.co/api/rest/stats/members'
    -H 'Authorization: Bearer {key}'
  

Make sure to replace {key} with your API key.

Response:

{
      "posts_count": 81,
      "posts_per_week": 0.75,
      "comments_count": 25,
      "comments_per_week": 0.25,
      "engaged_users_count": 21,
      "engaged_users_percent": 86,
      "new_members_count": 33,
      "post_views_count": 3194,
      "post_votes_up_count": 15,
      "post_votes_down_count": 7,
      "members": {
          "data": [
              {
                  "id": "123",
                  "name": "John Doe",
                  "posts": "31",
                  "comments": "971",
                  "post_views": "1256",
                  "read_posts": "100% (1250 of 1250)",
                  "logins": "1480"
              },
              {
                  "id": "456",
                  "name": "Jane Doe",
                  "posts": "1",
                  "comments": "3",
                  "post_views": "5",
                  "read_posts": "20% (250 of 1250)",
                  "logins": "368"
              }
          ],
          "meta": {
              "pagination": {
                  "total": 1,
                  "count": 1,
                  "per_page": 10,
                  "current_page": 1,
                  "total_pages": 1,
                  "links": {}
              }
          }
      }
  }
  

This endpoint retrieves members stats.

HTTP Request

GET https://blogin.co/api/rest/stats/members

GET https://blogin.co/api/rest/stats/users is an alias. It gives the same response.

Query Parameters

Parameter Default Description
start_date 30 days ago Start date (ISO-8601 format).
end_date today End date (ISO-8601 format).
page 1 The page number that the client is requesting (pagination).
limit 10 The number of resources to return per-page. Min. 1: a lower value answers 400. Values above 100 are reduced to 100.
sort -posts Sorting column. Available: name, posts, comments, post_views, read_posts, logins. See Sorting.
Example: GET https://blogin.co/api/rest/stats/members?sort=@name

Rate limits

A 429 response body. The message names the limit you passed:

{
    "message": "Rate Limit exceeded.",
    "code": 429
}

Two limits guard the API. Both answer 429 Too Many Requests, and both send a Retry-After response header with the number of seconds to wait. They do not both apply to every request, because each runs at a different point:

Limit Budget Counted per Message
Per API key 120 requests per 10-second window. The window starts at the key's first request and is fixed, not rolling: when it ends, the full budget is available again. The API key, after the key is authenticated. Rate Limit exceeded.
Per source IP address 50 requests per second The address the request comes from, across all API keys, before the key is read. Rate Limit exceeded. Too many requests from this IP address.

The IP limit allows a higher average rate than the per-key limit (50 against 12 requests per second), because an integration such as Zapier calls from shared addresses for many customers. Inside one window the order changes: a key's budget allows a burst of up to 120 requests, but one address can send at most 50 requests per one-second window, even when its key has budget left. Read the message field to learn which limit you passed. Then wait for the number of seconds in Retry-After and send the request again.

Errors

A failed validation names each field that did not pass:

{
    "message": "The given data failed to pass validation.",
    "code": 400,
    "errors": {
        "email": [
            "The email must be a valid email address."
        ]
    }
}

Every error response has the Content-Type application/json and carries a message field and a code field, where code repeats the HTTP status as an integer. A 401 response also has the header WWW-Authenticate: Bearer realm="Blogin REST API". A 405 response has an Allow header. A 429 and a 503 response have a Retry-After header with the number of seconds to wait.

A 400 caused by body or query validation carries a third field, errors. It is an object. Each key is a field name of your request, and each value is an array of messages for that field.

The BlogIn API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid. A field did not pass validation, the JSON body could not be parsed or is not a JSON object, a write field was sent in the query string, or the sort column is not one of the allowed columns. A validation failure adds the errors object.
401 Unauthorized -- The Authorization header is missing or not in Bearer {key} format, or the key is unknown, is not a REST API key, or belongs to an archived or closed company. A missing header answers Access denied. API key missing. All other cases answer Access denied, so the response does not show which case applied or whether a workspace exists. Every 401 has the header WWW-Authenticate: Bearer realm="Blogin REST API".
403 Forbidden -- The key is valid, but the request is refused:
1. The key does not have the permission that the endpoint needs: read permission for reads, write permission for create, update and delete. Set the permissions on the API tab of the Settings page.
2. The team is managed by your SSO integration, so its membership cannot change through the API.
3. The member is the company owner. The owner cannot be deleted, deactivated or given another role, or edited with a key that the owner did not create.
4. The post has comments disabled, or it is a draft, waits for approval or is scheduled, so you cannot add a comment.
404 Not Found -- The specified resource could not be found, or the URL does not match any endpoint. An id in the URL must be a positive integer written with digits: /members/5abc or /posts/1e3 is not found.
409 Conflict -- The request conflicts with the stored state. Today one cause: a changed post_poll on a poll that already has votes. Nothing is written. Omit post_poll to keep the poll, or send post_poll: null to delete it.
405 Method Not Allowed -- The URL exists, but not with this method. The allowed methods are in the Allow response header, for example Allow: GET, POST, and in the message: {"message": "Method not allowed. Must be one of: GET, POST.", "code": 405}.
413 Payload Too Large -- The request body is larger than 32 MB, or a base64 image in a post or comment text is above a limit (count, size, dimensions, or the 100-megapixel total of one text). See Create new post. Nothing is written.
415 Unsupported Media Type -- A post, comment or page text holds a data URI that the API does not extract: a file, a data URI that is not base64, an image format that is not supported, a data URI inside a <template> element or an <iframe srcdoc> value, or any data URI in page text. Nothing is written.
429 Too Many Requests -- Rate limit exceeded. See Rate limits.
500 Internal Server Error -- We had a problem with our server. Try again later. An unexpected error answers Internal server error. Other 500 answers describe the failure, for example an image that could not be stored; nothing is saved then. A post create or update is atomic: when the save fails, the post and its categories, tags, poll, teams and scheduled notification stay as they were (a create stores nothing), so you can safely send the same request again. A failure after the save, such as a notification that cannot be sent, does not change the success response.
503 Service Unavailable -- The service is temporarily not available, for example during maintenance. Nothing is written. Send the request again after the number of seconds in the Retry-After header.