ghost

package module
v0.0.0-...-d755f49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2025 License: MIT Imports: 13 Imported by: 0

README

Unofficial Go Client for Ghost Blogs

Not affiliated in any way with Ghost.org.

Ghost Client (ContentAPI + AdminAPI)

Installation

go get github.com/sklinkert/ghost

Supported features

Posts
  • Get posts (Content API + Admin API)
  • Get post by ID
  • Get posts by tag
  • Add post
  • Update post
  • Delete post
  • Search posts
Pages
  • Get pages (Content API + Admin API)
  • Get page by ID
  • Add page
  • Update page
  • Delete page
Tags
  • Get tags
  • Add tags
  • Update tag
  • Delete tag
Members
  • Get members (with pagination)
  • Get member by ID
  • Add member
  • Delete member
Images
  • Upload image

Usage

Initialization
package main

import (
	"github.com/sklinkert/ghost"
	"net/http"
	"time"
)

func main() {
	contentAPIToken := "837484..."
	adminAPIToken := "90968696..."

	// Default usage
	ghostAPI := ghost.New("https://example.com", contentAPIToken, adminAPIToken)

	// With custom HTTP client
	customClient := &http.Client{
		Timeout: 30 * time.Second,
	}
	ghostAPI = ghost.New("https://example.com", contentAPIToken, adminAPIToken, customClient)
}
Posts
// Get all posts (Content API)
posts, err := ghostAPI.GetPosts()

// Get all posts (Admin API)
posts, err := ghostAPI.AdminGetPosts()

// Get post by ID
posts, err := ghostAPI.AdminGetPost("628f557f0a8ce9486eb37623")

// Get posts by tag
posts, err := ghostAPI.AdminGetPostsByTag("news")

// Search posts
posts, err := ghostAPI.AdminSearchPosts("search query")

// Create a new post
newPost := ghost.Post{
	Title:  "My New Post",
	HTML:   "<p>Post content here</p>",
	Status: ghost.StatusPublished,
}
posts, err := ghostAPI.AdminCreatePost(newPost)

// Update a post
post.Title = "Updated Title"
err := ghostAPI.AdminUpdatePost(post, ghost.SourceHTML)

// Delete a post
err := ghostAPI.AdminDeletePost("628f557f0a8ce9486eb37623")
Pages
// Get all pages (Content API)
pages, err := ghostAPI.GetPages()

// Get all pages (Admin API)
pages, err := ghostAPI.AdminGetPages()

// Get page by ID
pages, err := ghostAPI.AdminGetPage("628f557f0a8ce9486eb37623")

// Create a new page
newPage := ghost.Page{
	Title:  "My New Page",
	HTML:   "<p>Page content here</p>",
	Status: ghost.StatusPublished,
}
pages, err := ghostAPI.AdminCreatePage(newPage)

// Update a page
page.Title = "Updated Title"
err := ghostAPI.AdminUpdatePage(page, ghost.SourceHTML)

// Delete a page
err := ghostAPI.AdminDeletePage("628f557f0a8ce9486eb37623")
Tags
// Get all tags
tags, err := ghostAPI.AdminGetTags()

// Create new tags
newTags := ghost.NewTags{
	Tags: []ghost.NewTag{
		{Name: "Technology", Slug: "technology"},
		{Name: "News", Slug: "news"},
	},
}
err := ghostAPI.AdminCreateTags(newTags)

// Update a tag
tag.Name = "Updated Name"
err := ghostAPI.AdminUpdateTag(tag)

// Delete a tag
err := ghostAPI.AdminDeleteTag(tag)
Members
// Get all members (with automatic pagination)
members, err := ghostAPI.AdminGetMembers()

// Get member by ID
members, err := ghostAPI.AdminGetMember("691ca681b7c6ec3a01a2ba81")
if err == nil && len(members.Members) > 0 {
	member := members.Members[0]
	fmt.Printf("Member: %s (%s)\n", member.Name, member.Email)
}

// Create a new member
newMember := ghost.NewMember{
	Name:  "John Doe",
	Email: "[email protected]",
}
members, err := ghostAPI.AdminCreateMember(newMember)

// Delete a member
err := ghostAPI.AdminDeleteMember("691ca681b7c6ec3a01a2ba81")
Images
// Upload an image
imageURL, err := ghostAPI.AdminUploadImage("./myimage.jpg")
if err != nil {
	fmt.Printf("Image upload failed: %v\n", err)
}
fmt.Println(imageURL)

API Reference

Client Initialization
func New(url, contentAPIToken, adminAPIToken string, client ...*http.Client) *Ghost
Posts
Method Description
GetPosts() Get all posts via Content API
GetPost(postId) Get a single post via Content API
GetPostsByTag(tag) Get posts by tag via Content API
AdminGetPosts() Get all posts via Admin API
AdminGetPost(postId) Get a single post via Admin API
AdminGetPostsByTag(tag) Get posts by tag via Admin API
AdminCreatePost(post) Create a new post
AdminUpdatePost(post, sourceType) Update an existing post
AdminDeletePost(postId) Delete a post
AdminSearchPosts(query) Search posts by title or excerpt
Pages
Method Description
GetPages() Get all pages via Content API
AdminGetPages() Get all pages via Admin API
AdminGetPage(pageId) Get a single page via Admin API
AdminCreatePage(page) Create a new page
AdminUpdatePage(page, sourceType) Update an existing page
AdminDeletePage(pageId) Delete a page
Tags
Method Description
AdminGetTags() Get all tags (with pagination)
AdminCreateTags(tags) Create new tags
AdminUpdateTag(tag) Update an existing tag
AdminDeleteTag(tag) Delete a tag
Members
Method Description
AdminGetMembers() Get all members (with pagination)
AdminGetMember(memberId) Get a single member by ID
AdminCreateMember(member) Create a new member
AdminDeleteMember(memberId) Delete a member
Images
Method Description
AdminUploadImage(path) Upload an image file

Documentation

Index

Constants

View Source
const StatusPublished = "published"

StatusPublished indicates if a post or pages is already published

Variables

This section is empty.

Functions

This section is empty.

Types

type Attribution

type Attribution struct {
	Id             interface{} `json:"id"`
	Type           string      `json:"type"`
	Url            string      `json:"url"`
	Title          string      `json:"title"`
	ReferrerSource string      `json:"referrer_source"`
	ReferrerMedium interface{} `json:"referrer_medium"`
	ReferrerUrl    interface{} `json:"referrer_url"`
}

type EmailSuppression

type EmailSuppression struct {
	Suppressed bool        `json:"suppressed"`
	Info       interface{} `json:"info"`
}

type Ghost

type Ghost struct {
	// contains filtered or unexported fields
}

func New

func New(url, contentAPIToken, adminAPIToken string, client ...*http.Client) *Ghost

New creates new instance of ghost API client

func (*Ghost) AdminCreateMember

func (g *Ghost) AdminCreateMember(member NewMember) (Members, error)

func (*Ghost) AdminCreatePage

func (g *Ghost) AdminCreatePage(page Page) (Pages, error)

func (*Ghost) AdminCreatePost

func (g *Ghost) AdminCreatePost(post Post) (Posts, error)

func (*Ghost) AdminCreateTags

func (g *Ghost) AdminCreateTags(tags NewTags) error

func (*Ghost) AdminDeleteMember

func (g *Ghost) AdminDeleteMember(memberId string) error

func (*Ghost) AdminDeletePage

func (g *Ghost) AdminDeletePage(pageId string) error

func (*Ghost) AdminDeletePost

func (g *Ghost) AdminDeletePost(postId string) error

func (*Ghost) AdminDeleteTag

func (g *Ghost) AdminDeleteTag(tag Tag) error

func (*Ghost) AdminGetMember

func (g *Ghost) AdminGetMember(memberId string) (Members, error)

func (*Ghost) AdminGetMembers

func (g *Ghost) AdminGetMembers() (Members, error)

func (*Ghost) AdminGetPage

func (g *Ghost) AdminGetPage(pageId string) (Pages, error)

func (*Ghost) AdminGetPages

func (g *Ghost) AdminGetPages() (Pages, error)

func (*Ghost) AdminGetPost

func (g *Ghost) AdminGetPost(postId string) (Posts, error)

func (*Ghost) AdminGetPosts

func (g *Ghost) AdminGetPosts() (Posts, error)

func (*Ghost) AdminGetPostsByTag

func (g *Ghost) AdminGetPostsByTag(tag string) (Posts, error)

func (*Ghost) AdminGetPostsPaginated

func (g *Ghost) AdminGetPostsPaginated(page, limit int, order string) (Posts, error)

AdminGetPostsPaginated returns a single page of posts with pagination metadata. Use this instead of AdminGetPosts when dealing with large numbers of posts. Parameters:

  • page: 1-indexed page number
  • limit: number of posts per page (max 100)
  • order: sort order, e.g. "published_at desc", "updated_at desc", "title asc"

func (*Ghost) AdminGetTags

func (g *Ghost) AdminGetTags() (Tags, error)

func (*Ghost) AdminSearchPosts

func (g *Ghost) AdminSearchPosts(query string) (Posts, error)

AdminSearchPosts searches for posts matching the query in title or custom_excerpt. Uses Ghost Admin API filter to search server-side across all posts.

func (*Ghost) AdminUpdatePage

func (g *Ghost) AdminUpdatePage(page Page, sourceType SourceType) error

func (*Ghost) AdminUpdatePost

func (g *Ghost) AdminUpdatePost(post Post, sourceType SourceType) error

func (*Ghost) AdminUpdateTag

func (g *Ghost) AdminUpdateTag(tag Tag) error

func (*Ghost) AdminUploadImage

func (g *Ghost) AdminUploadImage(path string) (imageURL string, err error)

AdminUploadImage - Creates a new file upload http request

func (*Ghost) GetPages

func (g *Ghost) GetPages() (Pages, error)

func (*Ghost) GetPost

func (g *Ghost) GetPost(postId string) (Posts, error)

func (*Ghost) GetPosts

func (g *Ghost) GetPosts() (Posts, error)

func (*Ghost) GetPostsByTag

func (g *Ghost) GetPostsByTag(tag string) (Posts, error)

type Image

type Image struct {
	URL string
}

type ImageResponse

type ImageResponse struct {
	Images []Image
}

type Member

type Member struct {
	Id          string      `json:"id"`
	Uuid        string      `json:"uuid"`
	Email       string      `json:"email"`
	Name        string      `json:"name"`
	Note        interface{} `json:"note"`
	Geolocation interface{} `json:"geolocation"`
	Subscribed  bool        `json:"subscribed"`
	CreatedAt   time.Time   `json:"created_at"`
	UpdatedAt   time.Time   `json:"updated_at"`
	Labels      []struct {
		Id        string    `json:"id"`
		Name      string    `json:"name"`
		Slug      string    `json:"slug"`
		CreatedAt time.Time `json:"created_at"`
		UpdatedAt time.Time `json:"updated_at"`
	} `json:"labels"`
	Subscriptions    []Subscription   `json:"subscriptions"`
	AvatarImage      string           `json:"avatar_image"`
	Comped           bool             `json:"comped"`
	EmailCount       int              `json:"email_count"`
	EmailOpenedCount int              `json:"email_opened_count"`
	EmailOpenRate    *float64         `json:"email_open_rate"`
	Status           string           `json:"status"`
	LastSeenAt       *time.Time       `json:"last_seen_at"`
	UnsubscribeUrl   string           `json:"unsubscribe_url"`
	Tiers            []Tier           `json:"tiers"`
	EmailSuppression EmailSuppression `json:"email_suppression"`
	Newsletters      []Newsletter     `json:"newsletters"`
	Attribution      *Attribution     `json:"attribution,omitempty"`
}

type Members

type Members struct {
	Members []Member   `json:"members"`
	Meta    Pagination `json:"meta,omitempty"`
}

type NewMember

type NewMember struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type NewMembers

type NewMembers struct {
	Members []NewMember `json:"members"`
}

type NewTag

type NewTag struct {
	CreatedAt          time.Time `json:"created_at,omitempty"`
	Description        string    `json:"description,omitempty"`
	FeatureImage       string    `json:"feature_image,omitempty"`
	Id                 string    `json:"id,omitempty"`
	MetaDescription    string    `json:"meta_description,omitempty"`
	MetaTitle          string    `json:"meta_title,omitempty"`
	Name               string    `json:"name,omitempty"`
	Slug               string    `json:"slug,omitempty"`
	UpdatedAt          time.Time `json:"updated_at,omitempty"`
	Url                string    `json:"url,omitempty"`
	Visibility         string    `json:"visibility,omitempty"`
	TwitterImage       string    `json:"twitter_image,omitempty"`
	TwitterTitle       string    `json:"twitter_title,omitempty"`
	TwitterDescription string    `json:"twitter_description,omitempty"`
	CodeInjectionHead  string    `json:"codeinjection_head,omitempty"`
	CodeInjectionFoot  string    `json:"codeinjection_foot,omitempty"`
	CanonicalURL       string    `json:"canonical_url,omitempty"`
	AccentColor        string    `json:"accent_color,omitempty"`
}

NewTag - two struct because field "Count" must not exist when creating a new tag

type NewTags

type NewTags struct {
	Tags []NewTag `json:"tags"`
}

type Newsletter

type Newsletter struct {
	Id          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Status      string `json:"status"`
}

type Page

type Page struct {
	ID                 string `json:"id,omitempty"`
	UUID               string `json:"uuid,omitempty"`
	Title              string `json:"title,omitempty"`
	MobileDoc          string `json:"mobiledoc,omitempty"`
	Lexical            string `json:"lexical,omitempty"`
	Slug               string `json:"slug,omitempty"`
	HTML               string `json:"html,omitempty"`
	CommentID          string `json:"comment_id,omitempty"`
	FeatureImage       string `json:"feature_image,omitempty"`
	Featured           bool   `json:"featured,omitempty"`
	Page               bool   `json:"page,omitempty"`
	MetaTitle          string `json:"meta_title,omitempty"`
	MetaDescription    string `json:"meta_description,omitempty"`
	CreatedAt          string `json:"created_at,omitempty"`
	UpdatedAt          string `json:"updated_at,omitempty"`
	PublishedAt        string `json:"published_at,omitempty"`
	CustomExcerpt      string `json:"custom_excerpt,omitempty"`
	OGImage            string `json:"og_image,omitempty"`
	OGTitle            string `json:"og_title,omitempty"`
	OGDescription      string `json:"og_description,omitempty"`
	TwitterImage       string `json:"twitter_image,omitempty"`
	TwitterTitle       string `json:"twitter_title,omitempty"`
	TwitterDescription string `json:"twitter_description,omitempty"`
	CustomTemplate     string `json:"custom_template,omitempty"`
	URL                string `json:"url,omitempty"`
	Excerpt            string `json:"excerpt,omitempty"`
	Status             string `json:"status,omitempty"`
	Visibility         string `json:"visibility,omitempty"`
	Tags               []Tag  `json:"tags,omitempty"`
}

type Pages

type Pages struct {
	Pages []Page `json:"pages"`
}

type Pagination

type Pagination struct {
	Pagination struct {
		Page  int  `json:"page"`
		Limit int  `json:"limit"`
		Pages int  `json:"pages"`
		Total int  `json:"total"`
		Next  *int `json:"next"`
		Prev  *int `json:"prev"`
	} `json:"pagination"`
}

type Post

type Post struct {
	ID                 string         `json:"id,omitempty"`
	UUID               string         `json:"uuid,omitempty"`
	Title              string         `json:"title,omitempty"`
	Lexical            string         `json:"lexical,omitempty"`
	MobileDoc          string         `json:"mobiledoc,omitempty"`
	Slug               string         `json:"slug,omitempty"`
	HTML               string         `json:"html,omitempty"`
	CommentID          string         `json:"comment_id,omitempty"`
	FeatureImage       string         `json:"feature_image,omitempty"`
	Featured           bool           `json:"featured,omitempty"`
	Page               bool           `json:"page,omitempty"`
	MetaTitle          string         `json:"meta_title,omitempty"`
	MetaDescription    string         `json:"meta_description,omitempty"`
	CreatedAt          string         `json:"created_at,omitempty"`   // "2022-01-05T22:39:28.000Z"
	UpdatedAt          string         `json:"updated_at,omitempty"`   // "2022-04-02T16:01:24.000Z"
	PublishedAt        string         `json:"published_at,omitempty"` // "2022-01-19T06:31:00.000Z"
	CustomExcerpt      string         `json:"custom_excerpt,omitempty"`
	OGImage            string         `json:"og_image,omitempty"`
	OGTitle            string         `json:"og_title,omitempty"`
	OGDescription      string         `json:"og_description,omitempty"`
	TwitterImage       string         `json:"twitter_image,omitempty"`
	TwitterTitle       string         `json:"twitter_title,omitempty"`
	TwitterDescription string         `json:"twitter_description,omitempty"`
	CustomTemplate     string         `json:"custom_template,omitempty"`
	URL                string         `json:"url,omitempty"`
	Excerpt            string         `json:"excerpt,omitempty"`
	Tags               []Tag          `json:"tags,omitempty"`
	Status             string         `json:"status,omitempty"`     // "published"
	Visibility         string         `json:"visibility,omitempty"` // "public"
	PostRevisions      []PostRevision `json:"post_revisions,omitempty"`
}

type PostRevision

type PostRevision struct {
	ID          string `json:"id,omitempty"`
	PostID      string `json:"post_id,omitempty"`
	Lexical     string `json:"lexical,omitempty"`
	MobileDoc   string `json:"mobiledoc,omitempty"`
	CreatedAtTs int64  `json:"created_at_ts,omitempty"`
	CreatedAt   string `json:"created_at,omitempty"`
	Title       string `json:"title,omitempty"`
	PostStatus  string `json:"post_status,omitempty"`
	Reason      string `json:"reason,omitempty"`
	Author      struct {
		ID              string `json:"id,omitempty"`
		Name            string `json:"name,omitempty"`
		Slug            string `json:"slug,omitempty"`
		Email           string `json:"email,omitempty"`
		ProfileImage    string `json:"profile_image,omitempty"`
		CoverImage      string `json:"cover_image,omitempty"`
		Bio             string `json:"bio,omitempty"`
		Website         string `json:"website,omitempty"`
		Location        string `json:"location,omitempty"`
		Facebook        string `json:"facebook,omitempty"`
		Twitter         string `json:"twitter,omitempty"`
		Accessibility   string `json:"accessibility,omitempty"`
		Status          string `json:"status,omitempty"`
		MetaTitle       string `json:"meta_title,omitempty"`
		MetaDescription string `json:"meta_description,omitempty"`
		Tour            string `json:"tour,omitempty"`
		LastSeen        string `json:"last_seen,omitempty"`
		CreatedAt       string `json:"created_at,omitempty"`
		UpdatedAt       string `json:"updated_at,omitempty"`
	} `json:"author,omitempty"`
}

type Posts

type Posts struct {
	Posts []Post     `json:"posts"`
	Meta  Pagination `json:"meta,omitempty"`
}

type SourceType

type SourceType string
const (
	Sourcelexical SourceType = "lexical" // deprecated
	SourceHTML    SourceType = "html"
	SourceLexical SourceType = "lexical" // default
)

type Subscription

type Subscription struct {
	Id       string `json:"id"`
	Customer struct {
		Id    string `json:"id"`
		Name  string `json:"name"`
		Email string `json:"email"`
	} `json:"customer"`
	Status                  string    `json:"status"`
	StartDate               time.Time `json:"start_date"`
	DefaultPaymentCardLast4 string    `json:"default_payment_card_last4"`
	CancelAtPeriodEnd       bool      `json:"cancel_at_period_end"`
	CancellationReason      string    `json:"cancellation_reason"`
	CurrentPeriodEnd        time.Time `json:"current_period_end"`
	Price                   struct {
		Id       string `json:"id"`
		PriceId  string `json:"price_id"`
		Nickname string `json:"nickname"`
		Amount   int    `json:"amount"`
		Interval string `json:"interval"`
		Type     string `json:"type"`
		Currency string `json:"currency"`
	} `json:"price"`
}

type Tag

type Tag struct {
	CreatedAt          time.Time `json:"created_at,omitempty"`
	Description        string    `json:"description,omitempty"`
	FeatureImage       string    `json:"feature_image,omitempty"`
	Id                 string    `json:"id,omitempty"`
	MetaDescription    string    `json:"meta_description,omitempty"`
	MetaTitle          string    `json:"meta_title,omitempty"`
	Name               string    `json:"name,omitempty"`
	Slug               string    `json:"slug,omitempty"`
	UpdatedAt          time.Time `json:"updated_at,omitempty"`
	Url                string    `json:"url,omitempty"`
	Visibility         string    `json:"visibility,omitempty"`
	TwitterImage       string    `json:"twitter_image,omitempty"`
	TwitterTitle       string    `json:"twitter_title,omitempty"`
	TwitterDescription string    `json:"twitter_description,omitempty"`
	CodeInjectionHead  string    `json:"codeinjection_head,omitempty"`
	CodeInjectionFoot  string    `json:"codeinjection_foot,omitempty"`
	CanonicalURL       string    `json:"canonical_url,omitempty"`
	AccentColor        string    `json:"accent_color,omitempty"`
	Count              struct {
		Posts int `json:"posts,omitempty"`
	} `json:"count,omitempty,skip"`
}

type Tags

type Tags struct {
	Tags []Tag      `json:"tags"`
	Meta Pagination `json:"meta,omitempty"`
}

type Tier

type Tier struct {
	Id   string `json:"id"`
	Name string `json:"name"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL