Ranklify API

Version v1 · Base URL https://www.getranklify.com

The Ranklify API generates platform-optimized product listings for Amazon, Shopify, and WooCommerce. Send product details, get back a titled, keyword-rich, scored listing in one request. API access is available on the Agency plan.

Base URL

All requests go to:

https://www.getranklify.com/api/v1

Always use the www host. The apex domain (https://getranklify.com) issues a 308 redirect, and many HTTP clients drop the Authorization header when following a redirect, which would fail your request. Requests must be https.

Authentication

Authenticate with a secret API key in the Authorization header as a Bearer token:

Authorization: Bearer lfy_your_key_here
  • Create and revoke keys in your dashboard at /api-keys.
  • Keys start with lfy_ and are shown once at creation. Store them securely.
  • A key is a full credential. Keep it server-side; never ship it in client-side code or a public repo.
  • Requests without a valid Agency-plan key are rejected (see Errors).

Quickstart

Replace lfy_YOUR_KEY with a real key and run:

curl
curl -X POST https://www.getranklify.com/api/v1/generate \
  -H "Authorization: Bearer lfy_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "product_name": "Stainless Steel Pour-Over Kettle",
    "features": "Gooseneck spout, 1L, food-grade steel, keeps heat",
    "platform": "amazon",
    "tone": "Professional"
  }'

A 200 response returns a listing object plus metadata (see below).

POST /api/v1/generate

Generates a single optimized listing and saves it to your account history.

Headers

HeaderValue
AuthorizationBearer lfy_... (required)
Content-Typeapplication/json (required)

Request body

FieldTypeRequiredNotes
product_namestringYesMax 200 chars.
featuresstringYesKey features / selling points. Max 600 chars.
platformstringNoOne of amazon, shopify, woocommerce. Default amazon. Unknown values fall back to amazon.
tonestringNoOne of Professional, Energetic, Friendly, Luxury, Technical, Playful, Bold, Minimalist. Default Professional.
categorystringNoMax 100 chars.
pricestringNoFree-text price context (e.g. "$24.99 mid-range"), not a number. Max 100 chars.
customerstringNoTarget customer & use cases. Max 500 chars.
competitorsstringNoCompetitor URLs or market context. Max 300 chars.
brand_idstringNoTarget workspace/brand the listing is filed under. Defaults to your active brand. Must be one you own or you get brand_forbidden.

Unknown fields are ignored, so new optional fields can be added without breaking your integration.

Response shape

A successful call returns 200 with the envelope below. The listing object is a stable superset: every key is always present. Fields that don't apply to the chosen platform come back empty ("" or []), so you can write one parser for all platforms.

200 OK
{
  "api_version": "v1",
  "listing": {
    "title": "HYDROSTEEL Stainless Steel Pour-Over Kettle ...",
    "bullets": ["PRECISE POUR — ...", "BUILT TO LAST — ...", "..."],
    "description": "<p>...</p>",
    "keywords": ["pour over kettle", "gooseneck kettle", "..."],
    "backend_terms": "coffee kettle, drip kettle, ...",
    "focus_keyphrase": "",
    "meta_description": "",
    "product_tags": [],
    "seo_scores": {
      "keyword_density": 89,
      "readability": 92,
      "conversion_potential": 91,
      "platform_compliance": 95
    },
    "pro_tip": "Add a lifestyle image showing the spout mid-pour."
  },
  "listing_id": "b1c2...",
  "platform": "amazon",
  "tone": "Professional",
  "brand_id": "a9d4...",
  "usage": { "used": 12, "limit": 1000, "plan": "agency" }
}

Which listing fields are populated per platform

FieldAmazonShopifyWooCommerce
title, description, keywords, seo_scores, pro_tip
bullets (up to 5)
backend_terms (string)
meta_description
focus_keyphrase
product_tags (up to 8)

seo_scores holds four integers 0–100: keyword_density, readability, conversion_potential, platform_compliance.

Errors

Errors return a non-2xx status with a stable envelope. Branch on error.code, never on the human message (messages may change, codes will not).

{ "error": { "code": "invalid_api_key", "message": "Invalid or revoked API key." } }
StatuscodeMeaning
401missing_authorizationNo / malformed Authorization header.
401invalid_api_keyWrong format, unknown, or revoked key.
403plan_requiredKey owner is not on the Agency plan.
403brand_forbiddenbrand_id is not on this account.
410brand_archivedbrand_id refers to an archived brand.
400invalid_jsonBody is not valid JSON.
400validation_errorMissing required field or a field exceeds its limit.
403usage_limit_reachedMonthly generation limit hit.
429rate_limitedOver 10 requests/min for this key. Retry after the Retry-After header.
500internal_errorUnexpected server error. Safe to retry.

Rate limits & usage

  • Rate limit: 10 requests per minute per key. Exceeding returns 429 with a Retry-After: 60 header.
  • Usage: every successful generation counts against your plan's monthly quota, shared with the dashboard. The response's usage object reports used, limit, and plan.
  • Latency: generation is AI-backed and typically takes a few seconds up to ~30s. Set a client timeout of at least 60 seconds.

Versioning & breaking changes

The API is versioned in the URL path (/api/v1/...). Our commitments:

  • Additive changes ship without a version bump. We may add new optional request fields, new response fields, new endpoints, and new accepted enum values within v1. Build clients to tolerate unknown fields.
  • Breaking changes ship as a new major version (/v2). Breaking means removing or renaming a field, changing a field's type or meaning, making an optional field required, tightening validation, or changing the error shape.
  • Deprecation window: when a new major version ships, the previous version keeps working for at least 6 months.
  • Notice: we announce breaking changes in advance by email to API key owners, in the changelog below, and via Deprecation and Sunset response headers on the retiring version.

Code samples

cURL
curl -X POST https://www.getranklify.com/api/v1/generate \
  -H "Authorization: Bearer lfy_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "product_name": "Stainless Steel Pour-Over Kettle",
    "features": "Gooseneck spout, 1L, food-grade steel, keeps heat",
    "platform": "amazon",
    "tone": "Professional"
  }'
JavaScript (Node 18+ / fetch)
const res = await fetch("https://www.getranklify.com/api/v1/generate", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.RANKLIFY_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    product_name: "Stainless Steel Pour-Over Kettle",
    features: "Gooseneck spout, 1L, food-grade steel, keeps heat",
    platform: "amazon",
    tone: "Professional",
  }),
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(error.code + ": " + error.message);
}
const data = await res.json();
console.log(data.listing.title);
Python (requests)
import os, requests

resp = requests.post(
    "https://www.getranklify.com/api/v1/generate",
    headers={
        "Authorization": f"Bearer {os.environ['RANKLIFY_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "product_name": "Stainless Steel Pour-Over Kettle",
        "features": "Gooseneck spout, 1L, food-grade steel, keeps heat",
        "platform": "amazon",
        "tone": "Professional",
    },
    timeout=60,
)

if resp.status_code != 200:
    err = resp.json()["error"]
    raise RuntimeError(f"{err['code']}: {err['message']}")

print(resp.json()["listing"]["title"])
PHP (cURL)
<?php
$ch = curl_init("https://www.getranklify.com/api/v1/generate");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("RANKLIFY_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "product_name" => "Stainless Steel Pour-Over Kettle",
        "features"     => "Gooseneck spout, 1L, food-grade steel, keeps heat",
        "platform"     => "amazon",
        "tone"         => "Professional",
    ]),
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);
if ($status !== 200) {
    throw new Exception($data["error"]["code"] . ": " . $data["error"]["message"]);
}
echo $data["listing"]["title"];
Java (java.net.http)
import java.net.URI;
import java.net.http.*;

HttpClient client = HttpClient.newHttpClient();

String body = """
    {
      "product_name": "Stainless Steel Pour-Over Kettle",
      "features": "Gooseneck spout, 1L, food-grade steel, keeps heat",
      "platform": "amazon",
      "tone": "Professional"
    }
    """;

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://www.getranklify.com/api/v1/generate"))
    .header("Authorization", "Bearer " + System.getenv("RANKLIFY_API_KEY"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
    throw new RuntimeException("Request failed: " + response.body());
}
System.out.println(response.body());

OpenAPI & Postman

Import the API into your tooling:

Changelog

v1 · 2026-07-14
  • Errors now return a machine-readable error.code.
  • listing is a stable superset — every field is always present (empty when not applicable to the platform).
  • Responses include api_version, and echo the resolved tone and brand_id.
  • Added optional brand_id to file a listing under a specific workspace.
v1 · initial
  • POST /api/v1/generate — Bearer auth, Agency plan, 10 req/min per key.

Questions or need a higher rate limit? Get in touch.