Integrations / Connector API

GrowthAtlas Connector API v1

The open specification for integrating any website with GrowthAtlas. Receive AI-generated SEO content on your site, or push social posts into GrowthAtlas Social Hub.

v1 — Stable Bearer Auth HMAC-SHA256 (optional) Idempotency

GrowthAtlas Connector API v1

This document describes the GrowthAtlas Connector API v1 specification — the contract that all GrowthAtlas connectors (WordPress plugin, Laravel package, custom implementations) must implement.

GrowthAtlas uses this API to push content drafts to your website and to pull page/entity data for SEO analysis. As long as your site exposes these endpoints, GrowthAtlas can publish to it, regardless of platform.


Base URL

Connectors expose endpoints under a sub-path of your domain. The path prefix depends on the connector:

Connector Base path
WordPress plugin /wp-json/growthatlas/v1/
Laravel package /api/growthatlas/v1/
Custom connector Configured by you in the dashboard

Authentication

All requests from GrowthAtlas include a Bearer token:

Authorization: Bearer <your-api-key>

Optionally, connectors can verify an HMAC-SHA256 signature for additional security:

X-GrowthAtlas-Signature: sha256=<hmac>

The HMAC is computed as HMAC-SHA256(secret, request_body). The signing secret is configured in the connector settings and in the GrowthAtlas dashboard.


Request Headers

GrowthAtlas always sends the following headers:

Header Value
Authorization Bearer <api-key>
Content-Type application/json
Accept application/json
User-Agent GrowthAtlas/1.0 (+https://growthatlas.io)
X-GrowthAtlas-Version v1
Idempotency-Key ga_draft_{draft_id}_{attempt} (on POST)

Response Envelope

All responses must be JSON. Successful responses return HTTP 200 or 201. Error responses return 4xx or 5xx.

Success

{
  "success": true,
  "data": { ... }
}

Error

{
  "success": false,
  "message": "Human readable error message",
  "errors": { "field": ["validation error"] }
}

Endpoints

GET /health

Health check. Returns connector version and platform info.

Response:

{
  "success": true,
  "data": {
    "status": "ok",
    "connector": "wordpress",
    "connector_version": "1.0.0",
    "platform": "wordpress",
    "platform_version": "6.5.3",
    "php_version": "8.2.10",
    "growthatlas_api_version": "v1"
  }
}

GET /site-profile

Returns basic information about the website for context in content generation.

Response:

{
  "success": true,
  "data": {
    "name": "My Website",
    "url": "https://example.com",
    "description": "A brief description of the site",
    "language": "en",
    "platform": "wordpress",
    "timezone": "UTC",
    "post_types": ["post", "page", "product"],
    "taxonomies": ["category", "tag"]
  }
}

GET /pages

Returns a paginated list of published pages/posts for SEO analysis.

Query parameters:

Parameter Type Default Description
page int 1 Page number
per_page int 100 Items per page (max 100)

Response:

{
  "success": true,
  "data": [
    {
      "url": "https://example.com/my-post",
      "title": "My Post Title",
      "meta_description": "Brief description",
      "h1": "My Post Title",
      "word_count": 1500,
      "published_at": "2024-01-15T10:00:00Z"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total": 350,
    "last_page": 4
  }
}

GET /entities

Returns a paginated list of entities (products, categories, locations, etc.) for topical authority building.

Query parameters:

Parameter Type Default Description
page int 1 Page number
per_page int 100 Items per page (max 100)
type string null Filter by type (product, etc.)

Response:

{
  "success": true,
  "data": [
    {
      "id": "product-123",
      "type": "product",
      "name": "My Product",
      "slug": "my-product",
      "description": "Product description",
      "url": "https://example.com/products/my-product",
      "priority": 80,
      "metadata": {}
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "total": 45,
    "last_page": 1
  }
}

POST /content-drafts

Receives a content draft from GrowthAtlas and publishes or saves it as a draft on your site.

Idempotency: The Idempotency-Key header is sent on every request. Connectors must check whether a post with the same growthatlas_draft_id already exists (via meta/custom field) and skip re-creating it. Instead, return the existing post's URL.

Request body:

{
  "growthatlas_draft_id": 123,
  "growthatlas_brief_id": 456,
  "title": "10 Best CRM Tools for Startups in 2025",
  "slug": "best-crm-tools-startups-2025",
  "excerpt": "A concise excerpt for the post.",
  "body": "## Introduction\n\nMarkdown body content...",
  "body_html": "<h2>Introduction</h2><p>HTML body content...</p>",
  "body_format": "markdown",
  "meta_title": "10 Best CRM Tools for Startups | My Site",
  "meta_description": "Discover the top CRM tools for startups in 2025.",
  "faq": [
    {
      "question": "What is a CRM?",
      "answer": "A CRM is..."
    }
  ],
  "schema_json": {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "10 Best CRM Tools"
  },
  "featured_image_url": "https://images.unsplash.com/photo-123",
  "featured_image_alt": "CRM dashboard illustration",
  "internal_links": [
    {
      "anchor": "email marketing tools",
      "url": "/email-marketing-guide"
    }
  ],
  "tags": ["crm", "startups", "productivity"],
  "categories": ["Software Reviews"],
  "language": "en",
  "publish_status": "draft",
  "target_keyword": "best crm for startups",
  "seo_score": 87,
  "source": "growthatlas"
}

Fields:

Field Type Required Description
growthatlas_draft_id int yes Used for idempotency. Store in post meta.
growthatlas_brief_id int no Linked brief ID. Optional, store in meta.
title string yes Post title
slug string no URL slug. Auto-generate from title if empty.
excerpt string no Short description / excerpt
body string no Body content (markdown if body_format=markdown)
body_html string no Pre-rendered HTML body
body_format string no markdown or html. Default markdown.
meta_title string no SEO title. Set in Yoast/RankMath/AIOSEO if available.
meta_description string no SEO meta description.
faq array no FAQ items [{question, answer}]
schema_json object no Schema.org JSON-LD object
featured_image_url string no URL of the featured image to download and attach
featured_image_alt string no Alt text for the featured image
internal_links array no Suggested internal links [{anchor, url}]
tags array no Post tags
categories array no Post categories
language string no ISO language code. Default en.
publish_status string no draft or published. Default draft.
target_keyword string no Primary SEO keyword
seo_score int no GrowthAtlas SEO score (0-100)
source string no Always growthatlas

Response (success):

{
  "success": true,
  "data": {
    "external_id": "wp-post-4521",
    "url": "https://example.com/best-crm-tools-startups-2025",
    "status": "draft",
    "created": true
  }
}

Response (idempotent — already exists):

{
  "success": true,
  "data": {
    "external_id": "wp-post-4521",
    "url": "https://example.com/best-crm-tools-startups-2025",
    "status": "draft",
    "created": false
  }
}

Outbound Social / Inbound to GrowthAtlas

Your site (or any custom generator — ML pipeline, CMS, cron job) can push social packages into GrowthAtlas Social Hub. GrowthAtlas then manages approval, scheduling, and Instagram publishing. This is the reverse direction of the connector endpoints above (which receive SEO drafts from GrowthAtlas).

Laravel users: use the official package client (GrowthAtlas::social()->pushPost([...])) — see growthatlas/laravel-connector docs/inbound-social.md.

Base URL

https://growthatlas.io/api/inbound/v1

Authentication

Authorization: Bearer ga_in_…

Optional (accepted and forwarded by connector clients; reserved for a future server-side cache):

Idempotency-Key: <unique-string>

Server idempotency is keyed on external_id per Integration.

Generate the inbound token in GrowthAtlas under Integration → Inbound Social. It is separate from your site’s connector API key (ga_live_…).

Endpoints

Method Path Content-Type
GET /health
POST /social-posts application/json
POST /social-posts/multipart multipart/form-data
GET /social-posts/{id}

Rate limit: 60 requests per minute per token (HTTP 429 when exceeded).

Parameter reference

Field Type Required Description
external_id string yes Your stable id (idempotent per Integration). Max 191 characters.
format string yes feed_image | feed_video | reel | carousel | story
caption string no Post caption. Max 2200 characters.
hashtags string[] no Hashtag strings without #. Each max 100 characters.
scheduled_at ISO-8601 no Scheduling hint. Honored when intake mode allows; otherwise ignored.
social_profile_ids int[] no GrowthAtlas social profile IDs. Overrides Integration defaults.
intake_mode string no studio_draft | autopilot_queue | publish_now. Defaults to Integration setting.
media array yes 1–10 items. See Media.

Social profile IDs

Find profile IDs in GrowthAtlas under Social → Accounts. Set defaults on the Integration under Inbound Social → Default social profiles. Omit social_profile_ids to use defaults. If neither payload nor Integration provides profiles → 422 (destinations_required).

Media

Limits

Limit Value
Max file size (multipart upload) 300 MB
Max download size (URL mode) 300 MB (314,572,800 bytes)
URL download timeout 30 seconds
Max items per post 10
Allowed MIME types image/jpeg, image/png, image/webp, image/gif, video/mp4, video/quicktime

URL mode (JSON)

"media": [
  { "url": "https://cdn.example.com/a.mp4", "mime_type": "video/mp4" }
]
  • HTTPS only; publicly reachable URLs; no localhost or private IPs.
  • Redirects are not followed.
  • mime_type optional but recommended; must match detected type if provided.

Multipart

media[0], media[1], … as ordered file parts (carousel order). Same logical fields as JSON, sent as form fields. One mode per request (no mixed URL + file).

Intake modes

Mode Behavior
studio_draft Lands in Social Studio as draft with media and destinations.
autopilot_queue Schedules on the Integration’s linked Social Autopilot campaign cadence (linked campaign required).
publish_now Submits through project approval → publish pipeline. Never bypasses required approvals.

Idempotency and updates

  • Same external_id under one Integration returns the existing post (no duplicate media). This is the server’s idempotency key.
  • The optional Idempotency-Key header may be sent by clients but is not used for server-side deduplication in v1; it is reserved for a future optional cache layer.
  • Replace allowed while status is draft.
  • When status is not draft, the API returns the existing post unchanged (HTTP 200) — safe for idempotent retries; no recomposition or media re-ingest.

Responses

Success (200):

{
  "data": {
    "id": 12345,
    "external_id": "campaign-42-post-7",
    "status": "draft",
    "format": "reel",
    "scheduled_at": null,
    "studio_url": "https://growthatlas.io/app/projects/1/social/studio/12345/edit"
  }
}

Errors:

HTTP When
401 Missing or invalid inbound token
403 Inbound Social disabled on Integration
404 Unknown post id for this Integration
422 Validation, SSRF, unsupported media, missing destinations/campaign
429 Rate limit exceeded

Examples

curl (JSON)

curl -X POST https://growthatlas.io/api/inbound/v1/social-posts \
  -H "Authorization: Bearer ga_in_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "external_id": "campaign-42-post-7",
    "format": "reel",
    "caption": "Three tips for better engagement",
    "social_profile_ids": [123],
    "media": [{"url": "https://cdn.example.com/reel.mp4", "mime_type": "video/mp4"}]
  }'

curl (multipart)

curl -X POST https://growthatlas.io/api/inbound/v1/social-posts/multipart \
  -H "Authorization: Bearer ga_in_your_token_here" \
  -F 'external_id=campaign-42-post-7' \
  -F 'format=feed_image' \
  -F 'caption=Generated locally' \
  -F 'social_profile_ids[]=123' \
  -F 'media[0]=@/path/to/image.jpg;type=image/jpeg'

Python (requests)

import requests

response = requests.post(
    "https://growthatlas.io/api/inbound/v1/social-posts",
    headers={"Authorization": "Bearer ga_in_your_token_here"},
    json={
        "external_id": "ml-run-2026-07-23-post-1",
        "format": "feed_image",
        "caption": "AI-generated caption",
        "social_profile_ids": [123],
        "media": [{"url": "https://cdn.example.com/output.jpg", "mime_type": "image/jpeg"}],
    },
    timeout=60,
)
response.raise_for_status()
print(response.json()["data"]["studio_url"])

Rate Limiting

GrowthAtlas respects Retry-After headers if returned. Connectors may limit requests per minute at their discretion. Recommended defaults:

  • POST /content-drafts: 10 requests/minute
  • Import endpoints: 60 requests/minute
  • Inbound Social (POST /api/inbound/v1/social-posts): 60 requests/minute

Versioning

The current version is v1. Breaking changes will result in a new version (v2). Non-breaking additions (new optional fields) are made in-place without version bumps.

The version is included in all request paths and in the X-GrowthAtlas-Version header.


Security Checklist for Connector Implementors

  • Validate Authorization: Bearer token using constant-time comparison
  • Optionally verify X-GrowthAtlas-Signature HMAC-SHA256
  • Implement idempotency for POST /content-drafts using growthatlas_draft_id
  • Return proper HTTP status codes (200/201 for success, 4xx for errors)
  • Never expose sensitive data in error messages
  • Store API keys securely (encrypted, not in plain text)
  • Implement slug conflict resolution (suffix or idempotent update)

Official Connectors

Connector Install Docs
WordPress Plugin WordPress.org Plugin Directory or GitHub /connector-api#wordpress
Laravel Package composer require growthatlas/laravel-connector /connector-api#laravel
Custom (any stack) Build your own using this spec This document