Documentation
¶
Overview ¶
Package apiv1 holds the public API's request and response types. They are shared by the Lambda that serves the API, the Go client used by the CLI and the MCP server, and the usage report embedded in the dashboard.
Index ¶
- Constants
- type APIError
- type Account
- type AccountList
- type AnalyticsAccount
- type AnalyticsPlatformRow
- type AnalyticsPost
- type AnalyticsQuery
- type AnalyticsRange
- type AnalyticsReport
- type AnalyticsSummary
- type Client
- func (c *Client) CreatePost(ctx context.Context, req CreatePostRequest) (*Post, error)
- func (c *Client) CreateUpload(ctx context.Context, req CreateUploadRequest) (*Upload, error)
- func (c *Client) DeletePost(ctx context.Context, id string) (*DeletePostResponse, error)
- func (c *Client) GetAnalytics(ctx context.Context, query AnalyticsQuery) (*AnalyticsReport, error)
- func (c *Client) GetPost(ctx context.Context, id string) (*Post, error)
- func (c *Client) GetUpload(ctx context.Context, id string) (*Upload, error)
- func (c *Client) GetUsage(ctx context.Context) (*UsageReport, error)
- func (c *Client) ListAccounts(ctx context.Context) (*AccountList, error)
- func (c *Client) ListPosts(ctx context.Context, query ListPostsQuery) (*PostList, error)
- func (c *Client) ListProfiles(ctx context.Context) (*ProfileList, error)
- type CreatePostRequest
- type CreateUploadRequest
- type DeletePostResponse
- type Delivery
- type ErrorBody
- type ErrorDetail
- type ListPostsQuery
- type Operations
- type Post
- type PostList
- type Profile
- type ProfileList
- type Upload
- type UsageCounter
- type UsageLinkCounter
- type UsagePeriod
- type UsagePlan
- type UsageRateLimits
- type UsageReport
Constants ¶
const ( StatusScheduled = "scheduled" StatusPending = "pending" StatusProcessing = "processing" StatusPublished = "published" StatusFailed = "failed" StatusPartial = "partial" StatusCancelled = "cancelled" )
Post statuses as exposed by the API (lower case, "published" instead of the internal SUCCESS).
const ( CodeInsufficientScope = "insufficient_scope" CodeSubscriptionRequired = "subscription_required" CodeRateLimited = "rate_limited" CodeQuotaExceeded = "quota_exceeded" CodeValidation = "validation_error" CodeNotFound = "not_found" CodeInternal = "internal_error" )
Error codes returned in the error envelope.
const DefaultBaseURL = "https://api.postatron.com"
DefaultBaseURL is the production API host.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIError ¶
type APIError struct {
Status int
Code string
Message string
Details map[string]any
RetryAfter time.Duration
}
APIError is returned by Client for non-2xx responses.
type Account ¶
type Account struct {
ID string `json:"id"`
Platform string `json:"platform"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
Status string `json:"status"`
ProfileID string `json:"profile_id"`
ProfileName string `json:"profile_name"`
ConnectedAt time.Time `json:"connected_at"`
}
Account is a connected social account. Every account belongs to exactly one profile, and a profile holds at most one account per platform.
type AccountList ¶
type AccountList struct {
Data []Account `json:"data"`
}
AccountList is the response of GET /v1/accounts.
type AnalyticsAccount ¶ added in v1.1.0
type AnalyticsAccount struct {
ID string `json:"id"`
Platform string `json:"platform"`
Username string `json:"username"`
Followers int64 `json:"followers"`
Supported bool `json:"supported"`
// Status is "ok", "unsupported", "reconnect_required", "unavailable" or "error".
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
}
AnalyticsAccount says whether an account's numbers could be read.
type AnalyticsPlatformRow ¶ added in v1.1.0
type AnalyticsPlatformRow struct {
Platform string `json:"platform"`
Posts int `json:"posts"`
Likes int64 `json:"likes"`
Comments int64 `json:"comments"`
Views int64 `json:"views"`
}
AnalyticsPlatformRow totals one platform.
type AnalyticsPost ¶ added in v1.1.0
type AnalyticsPost struct {
Platform string `json:"platform"`
Username string `json:"username"`
URL string `json:"url"`
Text string `json:"text"`
PublishedAt string `json:"published_at"`
Likes *int64 `json:"likes"`
Comments *int64 `json:"comments"`
Views *int64 `json:"views"`
Reach *int64 `json:"reach"`
Saves *int64 `json:"saves"`
Impressions *int64 `json:"impressions"`
Clicks *int64 `json:"clicks"`
Follows *int64 `json:"follows"`
Engagement int64 `json:"engagement"`
FromPostatron bool `json:"posted_with_postatron"`
}
AnalyticsPost is one of the best performing posts in the window.
type AnalyticsQuery ¶ added in v1.1.0
type AnalyticsQuery struct {
// Range is 7d, 30d or 90d (default 30d).
Range string
// Platform limits the report to one platform, e.g. instagram.
Platform string
// AccountID limits the report to one connected account.
AccountID string
// Profile is a profile id or name.
Profile string
// Source is "all" (default) or "postatron" for posts made with Postatron only.
Source string
}
AnalyticsQuery holds the filters accepted by GET /v1/analytics.
type AnalyticsRange ¶ added in v1.1.0
type AnalyticsRange struct {
Key string `json:"key"`
Start string `json:"start"`
End string `json:"end"`
}
AnalyticsRange is the window the report covers.
type AnalyticsReport ¶ added in v1.1.0
type AnalyticsReport struct {
Range AnalyticsRange `json:"range"`
Summary AnalyticsSummary `json:"summary"`
PerPlatform []AnalyticsPlatformRow `json:"per_platform"`
TopPosts []AnalyticsPost `json:"top_posts"`
Accounts []AnalyticsAccount `json:"accounts"`
GeneratedAt string `json:"generated_at"`
Notes []string `json:"notes,omitempty"`
}
AnalyticsReport is the response of GET /v1/analytics. A metric a platform does not report is null, never a negative number.
type AnalyticsSummary ¶ added in v1.1.0
type AnalyticsSummary struct {
EngagementRate float64 `json:"engagement_rate_percent"`
EngagementRateBasis string `json:"engagement_rate_basis"`
Engagements int64 `json:"engagements"`
Reach int64 `json:"reach"`
Followers int64 `json:"followers"`
PostsThisPeriod int `json:"posts_this_period"`
}
AnalyticsSummary holds the headline numbers.
type Client ¶
Client calls the public API with an API key.
func (*Client) CreatePost ¶
CreatePost calls POST /v1/posts.
func (*Client) CreateUpload ¶ added in v1.1.0
CreateUpload calls POST /v1/media/uploads.
func (*Client) DeletePost ¶
DeletePost calls DELETE /v1/posts/{id}.
func (*Client) GetAnalytics ¶ added in v1.1.0
func (c *Client) GetAnalytics(ctx context.Context, query AnalyticsQuery) (*AnalyticsReport, error)
GetAnalytics calls GET /v1/analytics.
func (*Client) GetUsage ¶
func (c *Client) GetUsage(ctx context.Context) (*UsageReport, error)
GetUsage calls GET /v1/usage.
func (*Client) ListAccounts ¶
func (c *Client) ListAccounts(ctx context.Context) (*AccountList, error)
ListAccounts calls GET /v1/accounts.
func (*Client) ListProfiles ¶ added in v1.1.0
func (c *Client) ListProfiles(ctx context.Context) (*ProfileList, error)
ListProfiles calls GET /v1/profiles.
type CreatePostRequest ¶
type CreatePostRequest struct {
Content string `json:"content"`
AccountIDs []string `json:"account_ids,omitempty"`
Platforms []string `json:"platforms,omitempty"`
Profile string `json:"profile,omitempty"`
MediaURLs []string `json:"media_urls,omitempty"`
MediaIDs []string `json:"media_ids,omitempty"`
ScheduledAt *time.Time `json:"scheduled_at,omitempty"`
}
CreatePostRequest is the body of POST /v1/posts. Exactly one of AccountIDs or Platforms must be set. ScheduledAt omitted publishes immediately.
Profile (an id or a name from ListProfiles) limits Platforms to the accounts in that profile. It is required when a platform has an account in more than one profile, so a post never fans out to every client by accident.
MediaURLs are public https links the server downloads; MediaIDs are upload ids from CreateUpload. Instagram and TikTok need at least one image or video, YouTube a video.
type CreateUploadRequest ¶ added in v1.1.0
type CreateUploadRequest struct {
// Purpose is shown to the person on the upload page, e.g. "the launch video".
Purpose string `json:"purpose,omitempty"`
}
CreateUploadRequest is the body of POST /v1/media/uploads.
type DeletePostResponse ¶
type DeletePostResponse struct {
ID string `json:"id"`
Status string `json:"status"`
Cancelled bool `json:"cancelled"`
Message string `json:"message,omitempty"`
}
DeletePostResponse is the response of DELETE /v1/posts/{id}.
type Delivery ¶
type Delivery struct {
AccountID string `json:"account_id"`
Platform string `json:"platform"`
Username string `json:"username"`
Status string `json:"status"`
URL string `json:"url,omitempty"`
Error string `json:"error,omitempty"`
}
Delivery is the per-platform state of a post.
type ErrorBody ¶
type ErrorBody struct {
Error ErrorDetail `json:"error"`
}
ErrorBody is the JSON envelope for every non-2xx response.
type ErrorDetail ¶
type ErrorDetail struct {
Code string `json:"code"`
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
}
ErrorDetail carries a stable machine-readable code and a human message.
type ListPostsQuery ¶
type ListPostsQuery struct {
Status string
Platform string
// Profile is a profile id or name; only posts to its accounts are listed.
Profile string
From *time.Time
To *time.Time
Limit int
Cursor string
}
ListPostsQuery holds the filters accepted by GET /v1/posts.
type Operations ¶
type Operations interface {
CreatePost(ctx context.Context, req CreatePostRequest) (*Post, error)
ListPosts(ctx context.Context, query ListPostsQuery) (*PostList, error)
GetPost(ctx context.Context, id string) (*Post, error)
DeletePost(ctx context.Context, id string) (*DeletePostResponse, error)
ListAccounts(ctx context.Context) (*AccountList, error)
ListProfiles(ctx context.Context) (*ProfileList, error)
GetUsage(ctx context.Context) (*UsageReport, error)
GetAnalytics(ctx context.Context, query AnalyticsQuery) (*AnalyticsReport, error)
CreateUpload(ctx context.Context, req CreateUploadRequest) (*Upload, error)
GetUpload(ctx context.Context, id string) (*Upload, error)
}
Operations is the public API surface. Client implements it over HTTP; the MCP server and CLI consume it.
type Post ¶
type Post struct {
ID string `json:"id"`
Status string `json:"status"`
Content string `json:"content"`
MediaType string `json:"media_type"`
ContainsLink bool `json:"contains_link"`
ScheduledAt *time.Time `json:"scheduled_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
Deliveries []Delivery `json:"deliveries"`
}
Post is the API representation of a post.
type Profile ¶ added in v1.1.0
type Profile struct {
ID string `json:"id"`
Name string `json:"name"`
IsDefault bool `json:"is_default"`
Accounts []Account `json:"accounts"`
}
Profile groups connected accounts, typically one per brand or client. Every account has a Default profile; paid plans can add more.
type ProfileList ¶ added in v1.1.0
type ProfileList struct {
Data []Profile `json:"data"`
}
ProfileList is the response of GET /v1/profiles.
type Upload ¶ added in v1.1.0
type Upload struct {
ID string `json:"id"`
Status string `json:"status"`
UploadURL string `json:"upload_url,omitempty"`
Filename string `json:"filename,omitempty"`
ExpiresAt string `json:"expires_at"`
Hint string `json:"hint,omitempty"`
}
Upload is a slot a person drops a file into from the dashboard, for an agent that cannot send the bytes itself. Pass its ID to CreatePost as MediaIDs once Status is "ready".
type UsageCounter ¶
type UsageCounter struct {
Used int `json:"used"`
Limit int `json:"limit"`
Remaining int `json:"remaining"`
}
UsageCounter is a capped counter. Limit is what the plan includes each month and is also the hard stop: there is no overage on any plan.
type UsageLinkCounter ¶
type UsageLinkCounter struct {
Used int `json:"used"`
}
UsageLinkCounter counts link-containing destination-posts across all platforms.
type UsagePeriod ¶
UsagePeriod is the calendar month the counters belong to.
type UsagePlan ¶
type UsagePlan struct {
Code string `json:"code"`
Name string `json:"name"`
Interval string `json:"interval"`
Status string `json:"status"`
ConnectedAccounts int `json:"connected_accounts"`
MaxConnectedAccounts int `json:"max_connected_accounts"`
}
UsagePlan summarises the subscription the quota comes from.
type UsageRateLimits ¶
type UsageRateLimits struct {
WritesPerMinute int `json:"writes_per_minute"`
ReadsPerMinute int `json:"reads_per_minute"`
UploadsPerMinute int `json:"uploads_per_minute"`
// WritesPerHour is WritesPerMinute * 60, kept for clients written before
// the write window became per minute.
//
// Deprecated: use WritesPerMinute.
WritesPerHour int `json:"writes_per_hour"`
}
UsageRateLimits echoes the per-key limits applied to this plan.
type UsageReport ¶
type UsageReport struct {
Period UsagePeriod `json:"period"`
Plan UsagePlan `json:"plan"`
DestinationPosts UsageCounter `json:"destination_posts"`
LinkPosts UsageLinkCounter `json:"link_posts"`
XLinkPosts UsageCounter `json:"x_link_posts"`
ByPlatform map[string]int `json:"by_platform"`
RateLimits UsageRateLimits `json:"rate_limits"`
}
UsageReport is the response of GET /v1/usage. The dashboard renders the same structure.