REST API

Developer documentation

Integrate SEOsoft into your CI pipeline, client reporting dashboard, or internal tooling. Every endpoint accepts JSON and returns JSON.

API access is included in the Command plan

Sign up or upgrade to get your API key and start building.

See plans

Overview

The SEOsoft API gives you programmatic access to your websites, reports, and account data. You can use it to trigger scans from a CI pipeline, pull results into your own dashboard, or automate monitoring for client sites. All endpoints return JSON and follow predictable REST conventions.

Base URL

https://api.seosoft.app/api/public/v1
StatusMeaning
200 OKRequest succeeded
201 CreatedResource created (POST /reports)
204 No ContentResource deleted successfully
401 UnauthorizedMissing or invalid API key
403 ForbiddenYour plan does not include this endpoint
404 Not FoundResource does not exist or belongs to another account
422 Unprocessable EntityValidation error — see errors field
429 Too Many RequestsRate limit exceeded — retry after X-RateLimit-Reset

Authentication

All requests must include your API key as a Bearer token in the Authorization header. Keys are generated in Settings → API access and shown only once when created. Treat your key like a password — it grants full access to your account data.

curl https://api.seosoft.app/api/public/v1/account \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Rate limits

Requests are limited to 60 per minute per API key. Every response includes rate limit headers so you can track your usage:

HeaderDescription
X-RateLimit-LimitTotal requests allowed per minute
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying (only on 429)

Report creation (POST /reports) additionally counts against your plan's monthly scan quota — the same quota used when running scans from the dashboard. A 422 with quota_exceeded is returned when the monthly limit is reached.

Errors

All error responses use the same JSON envelope. The message field is always present. For 422 validation errors, the errors field maps field names to arrays of error strings.

// 401 Unauthorized
{
  "message": "Unauthenticated."
}

// 422 Unprocessable Entity
{
  "message": "The url field is required.",
  "errors": {
    "url": ["The url field is required."]
  }
}

// 422 Quota exceeded
{
  "message": "Monthly scan quota reached. Upgrade your plan to run more scans.",
  "errors": {
    "quota": ["quota_exceeded"]
  }
}

Account

GEThttps://api.seosoft.app/api/public/v1/account

Get account

Returns basic information about the authenticated account, including plan and identifiers.

Request

curl https://api.seosoft.app/api/public/v1/account \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Response schema

FieldTypeDescription
idintegerUnique account ID
namestringAccount display name
emailstringAccount email address
planstringCurrent plan slug (e.g. command, growth, free)
created_atstring (ISO 8601)Account creation timestamp

Response example

{
  "data": {
    "id": 42,
    "name": "David Smith",
    "email": "david@example.com",
    "plan": "command",
    "created_at": "2026-01-15T10:30:00Z"
  }
}

Websites

GEThttps://api.seosoft.app/api/public/v1/websites

List websites

Returns a paginated list of websites in your account, sorted by creation date by default.

Query parameters

ParameterTypeDescription
searchstringFilter by domain or label
search_bystringField to search against. Default: domain
sort_bystringcreated_at · domain · score · report_count. Default: created_at
sortstringasc or desc. Default: desc
per_pageinteger10 · 25 · 50 · 100. Default: 10
pageintegerPage number. Default: 1

Request

curl "https://api.seosoft.app/api/public/v1/websites?per_page=25&sort_by=score&sort=asc" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Response example

{
  "data": [
    {
      "id": 1,
      "domain": "example.com",
      "score": 78,
      "privacy": "public",
      "report_count": 12,
      "created_at": "2026-01-15T10:30:00Z",
      "updated_at": "2026-08-20T14:22:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 10,
    "total": 47,
    "last_page": 5
  }
}
GEThttps://api.seosoft.app/api/public/v1/websites/{id}

Get website

Returns a single website by its ID.

Response schema

FieldTypeDescription
idintegerWebsite ID
domainstringRegistered domain (e.g. example.com)
scoreinteger | nullLatest aggregate score (0–100). Null if no reports yet
privacystringpublic · private · password
report_countintegerTotal number of reports for this website
created_atstring (ISO 8601)When the website was added
updated_atstring (ISO 8601)Last modification timestamp

Request

curl https://api.seosoft.app/api/public/v1/websites/1 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
PATCHhttps://api.seosoft.app/api/public/v1/websites/{id}

Update website

Updates a website's privacy setting. Only the fields you send are changed.

Body parameters

ParameterTypeDescription
privacyinteger0 = public · 1 = private · 2 = password-protected
passwordstringRequired when privacy is 2. Min 4 characters.

Request

curl -X PATCH https://api.seosoft.app/api/public/v1/websites/1 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"privacy": 1}'
DELETEhttps://api.seosoft.app/api/public/v1/websites/{id}

Delete website

Permanently deletes a website and all its associated reports. This cannot be undone. Returns 204 with no body on success.

Request

curl -X DELETE https://api.seosoft.app/api/public/v1/websites/1 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Reports

GEThttps://api.seosoft.app/api/public/v1/reports

List reports

Returns a paginated list of reports across all your websites. Filter by website, result grade, or URL.

Query parameters

ParameterTypeDescription
website_idintegerFilter to a specific website
searchstringFilter by URL substring
resultstringexcellent · good · decent · poor — filter by grade
sort_bystringid · url · score · created_at. Default: created_at
sortstringasc or desc. Default: desc
per_pageinteger10 · 25 · 50 · 100. Default: 10
pageintegerPage number. Default: 1

Request

curl "https://api.seosoft.app/api/public/v1/reports?website_id=1&result=poor&per_page=25" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Response example

{
  "data": [
    {
      "id": 1,
      "url": "https://example.com/blog/post",
      "website_id": 1,
      "score": 72,
      "result": "decent",
      "checks_total": 48,
      "checks_passed": 35,
      "checks_warned": 8,
      "checks_failed": 5,
      "created_at": "2026-08-01T10:30:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 10,
    "total": 23,
    "last_page": 3
  }
}
GEThttps://api.seosoft.app/api/public/v1/reports/{id}

Get report

Returns a single report with full check-level detail. Use this to retrieve the complete results of a scan.

Response schema

FieldTypeDescription
idintegerReport ID
urlstringThe URL that was scanned
website_idinteger | nullAssociated website ID, if the URL belongs to a monitored website
scoreinteger | nullAggregate score (0–100)
resultstringexcellent · good · decent · poor — grade derived from score
checks_totalintegerTotal number of checks performed
checks_passedintegerChecks that passed
checks_warnedintegerChecks with warnings
checks_failedintegerChecks that failed
created_atstring (ISO 8601)When the scan was run

Request

curl https://api.seosoft.app/api/public/v1/reports/1 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
POSThttps://api.seosoft.app/api/public/v1/reports

Create report

Triggers a full SEO scan of the given URL and returns the completed report. This is a synchronous operation — the response is returned once the scan finishes (typically 5–15 seconds). Report creation counts against your monthly scan quota.

Body parameters

ParameterTypeDescription
urlrequiredstringThe full URL to scan, including https://. Must be publicly reachable.

Request

curl -X POST https://api.seosoft.app/api/public/v1/reports \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/landing-page"}'

Response example (201 Created)

{
  "data": {
    "id": 99,
    "url": "https://example.com/landing-page",
    "website_id": 1,
    "score": 81,
    "result": "good",
    "checks_total": 48,
    "checks_passed": 39,
    "checks_warned": 6,
    "checks_failed": 3,
    "created_at": "2026-09-01T08:14:22Z"
  }
}
DELETEhttps://api.seosoft.app/api/public/v1/reports/{id}

Delete report

Permanently deletes a report. Returns 204 with no body on success.

Request

curl -X DELETE https://api.seosoft.app/api/public/v1/reports/99 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"