/ ghost blog

How to upload photos to Ghost blog using private API?

Starting from v0.5.1 Picpipe allows a user to upload optimized photos straight to Ghost blog gallery. Image uploading API is undocumented part of Ghost Private API.
In this post, I'm going to explain how it was done in Picpipe so that you can implement it anywhere.

Getting Ghost Private API Token.

In order to generate API Token we need for values: your account email and password + client_id and client_secret. Ghost still doesn't have a good looking UI that generates those values, so we need to get our hands dirty and get the answer from the black screen.
The Matrix

  1. You will have to SSH to your hosting server. You should know how to do that with your setup. If you are hosting your blog on DigitalOcean, you can run ssh <user>@<droplet_ip> on the Terminal command line.

  2. Next we need to connect to MySQL database.
    If you are hosting Ghost with one-click installation, the passwords for it were carefully put in .digitalocean_password file.
    Run cat /root/.digitalocean_password to get it. Copy the password for root user to the clipboard - you will need it later.

  3. Now run mysql -u root -p and paste the password to log in.

  4. Connect to your Ghost database. If you do not remember the exact name - list all the tables using SHOW DATABASES; command.
    Connect to database buy running USE <your database name>;

The table we are looking for called clients. If you are interested what tables does Ghost have, run SHOW TABLES;. If not - SELECT * FROM clients;.

  1. You should see a table with all the allowed clients. Just pick one of them. In my case, I'll go with ghost-admin. The fields that you are looking for called slug and secret. The first is representing client_id and the second is client_secret - it should look like a sequence of random chars.

If you read this post to be able to setup Ghost with Picpipe - you can stop reading here Use the values that you've got to fill up the collection form.
Form to integrate Picpipe with Ghost blogging platform

Developers - keep reading!

Upload image to Ghost blog using Postman.

Let's first test the whole process using Postman for more visibility.

  1. Make sure you have all required credentials for authentication request:

This POST request to http://yourblog.com/ghost/api/v0.1/authentication/token should return JSON with access_token and token_type in response.

    "access_token": "<your token>",
    "refresh_token": "<refresh token>",
    "expires_in": 2628000,
    "token_type": "Bearer"

This token is used to autorize all following requests to Ghost API.

  1. Next, create another POST request in Postman. This is Ghost route used to upload photos: yourblog.com/ghost/api/v0.1/uploads.

You will need to add two HTTP headers to this request:

  • Authorization is basically token_type + space + access_token so just put it together as shown on the screenshot.
  • Content-Type - we are going to send an image file, and this header value should vary according to the image type you are sending: image/png and image/jpeg for png and jpg accordingly.
    How to upload images to ghost using ghost api
  1. Now add an image to the request body. Ghost API is expecting to get your image in the key uploadimage.

Change the key type to file as shown in the screenshot.
How to upload images to ghost using ghost api

If everything worked fine, you should receive a relative path to your new image.

That's it!

Upload image to Ghost using NodeJS.

I have put together a small code snippet to show you have to implement this upload request using Javascript:

const mime = require('mime-types');
const path = require('path');
const fs = require('fs');
const request = require('request');
const settings = require('electron-settings');

// Use absolute filepath.
const filepath = '<your_file_path>';

// This small lib will return image/png or image/jpeg
// based on file extension.
const type = mime.lookup(filepath);

const options = {
  url: 'https://yourblog.com/ghost/api/v0.1/uploads',
  headers: {
    'Content-Type': type,
    'Authorization': '<YOUR_TOKEN>'
  formData: {
    uploadimage: fs.createReadStream(filepath)

request.post(options, function(error, response, relative_url) {
  console.log('response', response.body)


We learned how to upload files to Ghost using private API. One thing that you have to pay attention to - Ghost Private API is undocumented and can be changed at any time. Make sure you keep your finger on the pulse when developing a client for this API.