NAV Navbar
php shell

API Reference

Welcome to BlogIn REST API.

BlogIn API is organized around endpoints, such as the Member API, or the Post API. You can use these endpoints to get or post data about the specific item.

All requests should be made over SSL. Request and response bodies, including errors, are encoded in JSON. The one exception is the 204 response of a resource delete, which has no body. Every error response is JSON, as described under Errors.

Success status codes. A read answers 200. A create answers 201 and returns the new resource. An update answers 200 and returns the updated resource. A delete of a resource (a member, post, comment, page, category or team) answers 204 No Content, with no body. The one exception is DELETE /members/:memberId/teams/:teamId: it changes a membership, not a resource, and answers 200 with the team list of the member. Treat any 2xx as success, and read the status before you parse the body.

Every update is a partial update. One rule applies to every POST update route: a field you leave out keeps its stored value; an explicit null clears it, where clearing is allowed; false, 0 and "" are values and are written. Send only the fields you want to change. These are merge-patch-style semantics: omitted fields are kept, a supplied array replaces the stored list as a whole, and null removes. They are 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.

Three shapes are not interchangeable:

Fields that refuse null (400): title, text, author.id (except on a post, comment or page without an author: see Update a post), 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. A post date_published accepts null only when the post is not published after the request, so {"published": false, "date_published": null} is accepted and {"published": true, "date_published": null} is a 400.

Send write fields in the request body. The query string never writes anything. A field of the route that you send in the query string answers 400, naming the field: title must be sent in the request body; this endpoint does not read write fields from the query string. The body is read as JSON whatever the Content-Type header says.

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

Links to uploaded files in text. A post or page text in a response carries absolute links to the workspace's uploaded images and files, each with an access token (?gt=…), so that they open outside BlogIn. When you send text in a create or an update, these links are stored in their normal form again. A valid access token is removed from every link to this workspace's upload folder, whatever the address in front of it, because a response adds the token again. The workspace address is removed only from links to this workspace. All other links are stored 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.

We also have some examples for specific language binding to make integration easier. You can switch the programming language of the examples with the tabs in the top right.

Currently, we have examples for the following languages:

To test your API requests, we recommend using a REST client called Postman. Click the button below to import a pre-made collection of request examples.

Authentication

Authentication is done via the API key which can be generated on the API tab of the Settings page of your BlogIn account (please note that you have to be an administrator to be able to access this page).

Requests are authenticated by passing 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}'

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 or Reader. The level numbers "20", "15", "10", "5" and "2" are also accepted. Any other value answers 400.
In a response, the API returns the level number as a string: "20" Administrator, "15" Reviewer, "10" Writer, "5" Commenter, "2" Reader.
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. 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. At most 25 characters: letters A-Z and a-z, digits, _, . and -; any other value, null and "" are a 400. Omit the field to build the username from the email address. When the username is already used in the workspace (letter case is ignored, so Ann and ann are the same), BlogIn adds a suffix such as .4821, so a stored username can have up to 31 characters. The response returns the stored username. If another request takes the same username or email at the same moment, the create answers 409; send the request again.
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, each with an id field, for the Teams the new member joins. Example: [{"id": 123}]

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.
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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. The same rules as on create: at most 25 characters of A-Z, a-z, digits, _, . and -, unique in the workspace (letter case is ignored), otherwise a 400. The member's own current username is accepted. A sent username is stored exactly as sent. If another request takes the same username at the same moment, the update answers 409. Omit the field to keep the stored username. Exception: an older username with @ is stored with . in its place on any update, and gets a suffix such as .4821 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, by name: Administrator, Reviewer, Writer, Commenter or Reader, or by the numeric level that responses return: 20, 15, 10, 5 or 2. Any other value, "" included, is a 400. The role changes only when you send this field. The company owner role 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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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: Check HTTP response status code (200 OK, 4xx or 5xx for 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: Check HTTP response status code (200 OK, 4xx or 5xx for 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

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, an omitted author keeps the author, and null removes it. A post without an author, or whose author was deleted, returns an author object with "id": null: {"id": null, "name": "Jane Doe", "avatar": null}. The name is the one the author had when they were deleted, or "Unknown". Sending that 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. read-only
votes_down int Number of votes down. 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 is shown on the post. Optional. When you omit it, a poll that the post already has keeps its state (a draft stays a draft), and a new poll is published. false stores the poll as a draft, which may be incomplete: the question may be empty, and it may have fewer than two answers, as the web editor saves a poll that is not finished yet. true publishes it, and then a question and two answers are required.
answers array Array of the poll answer values. mandatory when you send post_poll.
On create or update, send each answer as an object with a text field, and send at least two that are not empty. A draft poll may send fewer. An answer is stored trimmed, and "0" is a valid answer. In a response each answer carries id, poll_id, text, votes_count 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 published date and time (ISO-8601 format). Send the offset with the value, and the API converts the value to the time zone of the server before it stores it. The response returns the stored value with the server offset, so it can differ from what you sent while it names the same moment. Default: now, when published is true. Example: 2021-11-01T11:12:44+00:00
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) mandatory
categories Array of objects containing Category name OR ID. See example. An entry with an id is looked up by id first, then by name. A name can be "Parent/Child" to name a subcategory. A wrong entry never rejects the post: an unknown category, a category of another workspace, or a locked category the post does not already have is skipped, and the response lists each skipped entry in meta.warnings, for example {"id": 3562, ..., "meta": {"warnings": ["category id 99 not found, skipped", "category \"News\" is locked, skipped"]}}. With no skipped entry the response has no meta key. At most 20 warnings are listed, then one line counts the rest. An id is a JSON integer or a string of digits.
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 containing IDs of Team(s) to notify when this post is published. Ignored unless notify is true. The legacy entry {"id": -1} still means "notify all users", but notify_all_users is the field to use; -1 is never returned.
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 containing IDs of Team(s) that can see this post. The legacy entry {"id": -1} still means "visible to all users", but visible_all_users is the field to use; -1 is never returned.
tags Array of tags of the post.
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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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.
categories Array of objects containing Category name OR ID. Omit to keep the current categories; send [] or null to clear them. When you send a list and no entry in it is found, the current categories are kept and meta.warnings says so. See example. An entry with an id is looked up by id first, then by name. A name can be "Parent/Child" to name a subcategory. A wrong entry never rejects the post: an unknown category, a category of another workspace, or a locked category the post does not already have is skipped, and the response lists each skipped entry in meta.warnings, for example {"id": 3562, ..., "meta": {"warnings": ["category id 99 not found, skipped", "category \"News\" is locked, skipped"]}}. With no skipped entry the response has no meta key. At most 20 warnings are listed, then one line counts the rest. An id is a JSON integer or a string of digits.
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. 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. Never stored, never returned.
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 containing IDs of Team to notify. Replaces the stored recipients when notify is on; ignored when it is off. [] or null clears them either way. The legacy entry {"id": -1} still means "notify all users"; -1 is never returned.
visibility_teams WORKS ONLY WITH POST VISIBILITY FEATURE Array of objects containing IDs of Team(s) that can see this post. [] or null clears them. The legacy entry {"id": -1} still means "visible to all users"; -1 is never returned.
tags Array of tags of the post: names, or tag objects with a name as a response returns them. Replaces the stored tags; [] or null clears them.
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, an omitted author keeps the author, and null removes it. A comment without an author, or whose author was deleted, returns an author object with "id": null, the name the author had when they were deleted (or "Unknown"), and "avatar": null. Sending that 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.

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. 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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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.
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 whose author was deleted, returns {"id": null, "name": "Unknown", "avatar": null}. Sending that 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 The text of the page, HTML format. Base64 data URIs are not supported in page text: a data URI in a src, href, srcset or poster attribute, or in the data attribute of an <object>, answers 415, also inside a <template> element or an <iframe srcdoc> value. mandatory
author The object containing the ID of the author of the page. 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, used to custom sort the resource (float). Omitted or null: the page goes to the end. 0 is stored as 0.

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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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 The text of the page, HTML format. A data URI in a src, href, srcset or poster attribute, or in the data attribute of an <object>, answers 415, also inside a <template> element or an <iframe srcdoc> value, as on create.
author The object containing the ID of the author of the page. null removes the author.
published Published flag (true/false).
position Sort position, used to custom sort the resource (float).

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 The position of the category (float). Omitted or null: the category goes to the end. 0 is stored as 0.
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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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.
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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.
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.

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 The ID of the parent category. Omitted: unchanged. null makes the category a root category.
name The name of the category. Omitted: unchanged.
position The position of the category. Omitted: unchanged. null moves it to the end; 0 is stored as 0. A decimal, such as 2.5, is 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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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 The position of the team (float). Omitted or null: the team goes to the end. 0 is stored as 0.
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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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 The position of the team (sort order). Omitted: unchanged. null moves it to the end; 0 is stored as 0. A decimal, such as 2.5, is 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 The request fails validation without it, or when it is longer than 255 characters.
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.
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.

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.

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.
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_countPost views in the period.
post_votes_up_countUp votes on posts in the period.
post_votes_down_countDown votes on posts in the period.

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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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
Use prefixes '@' (for ascending) or '-' (for descending) to specify sort direction.
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 request has no Authorization header, the header is not in Bearer {key} format, the key is unknown, the key is not a REST API key, or the company of the key is archived or closed. A missing header answers Access denied. API key missing. The other four all answer Access denied, so the API does not tell whether a workspace exists or which of them applied. Every 401 has the header WWW-Authenticate: Bearer realm="Blogin REST API".
403 Forbidden -- The request is refused although the key is valid. Three causes:
1. The key does not hold the permission the endpoint needs. Every read endpoint needs read permission, and every create, update or delete endpoint needs write permission. 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, and the owner cannot be deleted, deactivated, given another role, or edited with a key that the owner did not create.
404 Not Found -- The specified resource could not be found, or the URL does not match any endpoint.
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.
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.