ఇంటిగ్రేషన్ను ప్రారంభించండి
- Admin → API & integrationsలో మీ అప్లికేషన్ను సృష్టించమని నిర్వాహకుడిని అడగండి. ప్రతి అప్లికేషన్కు ప్రత్యేక వాతావరణం, కంటెంట్ పరిధులు, ఛానెల్లు, భాషలు, రచయితలు, గడువు మరియు అభ్యర్థన కోటా ఉంటాయి.
- క్రెడెన్షియల్ను మీ సర్వర్లో భద్రపరచండి. ప్రొడక్షన్లో ft_live_ క్రెడెన్షియల్స్ను, సాండ్బాక్స్లో ft_test_ క్రెడెన్షియల్స్ను ఉపయోగించండి. ప్రతి అభ్యర్థనతో Authorization: Bearer <credential> పంపండి.
- అనుమతించబడిన రచయిత మరియు అంశాల IDలను పొందడానికి /capabilities మరియు /content/taxonomies చదవండి. మీ డాక్యుమెంట్ను సిద్ధం చేయడానికి OpenAPIలోని స్కీమాను ఉపయోగించండి.
- డ్రాఫ్ట్ను సృష్టించి, సమీక్షకు సమర్పించి, ప్రచురణ ఈవెంట్లను పర్యవేక్షించండి. ఎడిటర్ విడుదలకు బాధ్యత వహిస్తూనే, మీ ఆటోమేషన్ ఉపయోగకరమైన కంటెంట్ను సిద్ధం చేయగలదు.
బేస్ URL: https://www.formtruth.com/integrations/v1
కంటెంట్ మరియు ప్రచురణ
విడుదలకు ముందు ప్రతి బాహ్య డ్రాఫ్ట్కు దాని ప్రస్తుత కంటెంట్పై సిబ్బంది ఆమోదం అవసరం. ప్రకటించిన మానవ రచన పద్ధతి లేదా స్వయంచాలిత ప్రచురణ సెట్టింగ్ సంపాదకీయ ఆమోదాన్ని మంజూరు చేయదు.
పోస్ట్లు, కొనుగోలుదారుల మార్గదర్శకాలు మరియు తరచుగా అడిగే ప్రశ్నలు ఒకే డాక్యుమెంట్ ఫార్మాట్ మరియు వెర్షన్ చరిత్రను పంచుకుంటాయి. సంబంధిత అనుమతితో /content/posts, /content/guides లేదా /content/faqsను ఉపయోగించండి. అప్లికేషన్లు తమకు చెందిన కంటెంట్ను మాత్రమే యాక్సెస్ చేయగలవు; ప్రైవేట్ డ్రాఫ్ట్ను చదవడం, ప్రచురించబడిన వెబ్సైట్ను చదవడం కంటే భిన్నం.
డాక్యుమెంట్లలో మూల భాష, నిజమైన రచయిత, అంశాలు, మూలాలు, అలాగే స్థానికీకరించిన శీర్షికలు, స్లగ్లు, సారాంశాలు మరియు నిర్మిత బాడీ బ్లాక్లు ఉంటాయి. AI సహాయంతో లేదా ఆటోమేటెడ్గా రూపొందించిన వ్యాసాలు తమ పాఠకుడి లక్ష్యం మరియు అసలు సహకారాన్ని గుర్తించాలి. అనువాద సవరణలు ఉత్పత్తి వాస్తవాలు, సంఖ్యలు, చిత్ర IDలు, లింకులు లేదా నిర్మాణ పరిమాణాలను మార్చకూడదు.
ప్రతి రైట్కు Idempotency-Key అవసరం. అప్డేట్లు, సమీక్ష, ప్రచురణ మరియు ఉపసంహరణకు కూడా కోట్ చేయబడిన ETag తో If-Match అవసరం. సమీక్షించిన కంటెంట్ను సవరించడం ప్రభావిత ఆమోదాన్ని చెల్లుబాటు కాకుండా చేస్తుంది. మూలాన్ని మార్చడం వల్ల ప్రభావిత అనువాదాలు మళ్లీ సమలేఖనం చేయబడి సమీక్షించబడే వరకు పాతవిగా మారతాయి.
ఎడిటర్ హక్కులు మరియు నాణ్యతను తనిఖీ చేసే వరకు అప్లోడ్ చేసిన చిత్రాలు ఆమోదించబడవు. ప్రచురించబడిన విడుదలలు మార్పులేని స్నాప్షాట్లుగా ఉంటాయి. ఉపసంహరణ వల్ల విడుదల పబ్లిక్ కంటెంట్, ఫీడ్లు మరియు శోధనలో కనిపించదు.
API సూచన
క్రింది పాత్లు బేస్ URLకు సంబంధితంగా ఉంటాయి. కంటెంట్ కుటుంబాన్ని మార్చడం ద్వారా ఇదే వ్యాస మార్గాలను గైడ్లు మరియు తరచుగా అడిగే ప్రశ్నలకు కూడా ఉపయోగించవచ్చు. పూర్తి అభ్యర్థన స్కీమాలు, అవసరమైన పరిధులు మరియు ప్రతిస్పందనల కోసం OpenAPIని డౌన్లోడ్ చేయండి.
| పద్ధతి | పాత్ | ప్రయోజనం |
|---|
GET | /capabilities | మీకు అమలులో ఉన్న అనుమతులు మరియు పరిమితులు |
GET / POST | /content/posts | మీ వ్యాసాలను జాబితా చేయండి / డ్రాఫ్ట్ను సృష్టించండి |
GET / PATCH | /content/posts/{id} | డ్రాఫ్ట్ మరియు ETagను చదవండి / సవరణను భద్రపరచండి |
PUT | /content/posts/by-external-id/{externalId} | మీ స్థిరమైన బాహ్య ID ద్వారా డ్రాఫ్ట్ను సృష్టించండి లేదా నవీకరించండి |
POST | /content/posts/{id}/submit-review | సంపాదకీయ సమీక్షకు సమర్పించండి |
POST | /content/posts/{id}/publications | ఆమోదించబడిన భాషలను ప్రచురించండి లేదా విడుదలను షెడ్యూల్ చేయండి |
DELETE | /content/posts/{id}/publications/{releaseId} | కారణంతో విడుదలను ఉపసంహరించండి |
GET | /content/taxonomies | క్రియాశీల అంశాలు మరియు అనుమతించబడిన రచయితలు |
POST | /content/imports | 50 వరకు డ్రాఫ్ట్లను క్యూలో ఉంచి, అంశాల ఫలితాలను పరిశీలించండి |
POST | /assets/uploads | హక్కులు మరియు నాణ్యత సమీక్ష కోసం చిత్రాన్ని అప్లోడ్ చేయండి |
POST | /assets/{id}/complete | భద్రపరచబడిన అప్లోడ్ స్థితిని చదవండి |
GET | /jobs/{id} | మీ దిగుమతి ఫలితాలను చదవండి |
GET / POST | /webhooks/subscriptions | మీ HTTPS ఈవెంట్ రిసీవర్లను జాబితా చేయండి లేదా నమోదు చేయండి |
POST | /webhooks/subscriptions/{id} | కీని నవీకరించండి, మార్చండి లేదా డెలివరీని నిలిపివేయండి |
క్యాటలాగ్, ఆర్డర్లు మరియు ఇన్వెంటరీ తరువాతి API మాడ్యూళ్ల కోసం కేటాయించబడ్డాయి. అవి ఇంకా ఈ v1 గేట్వే ద్వారా అందుబాటులో లేవు.
లోపాలు మరియు మళ్లీ ప్రయత్నాలు
కుదించబడని UTF-8 JSON పంపండి. రిక్వెస్ట్ బాడీ పరిమితులు సాధారణ రైట్లకు 2 MiB, దిగుమతులకు 8 MiB మరియు ఎన్కోడ్ చేయబడిన ఇమేజ్ అప్లోడ్లకు 18 MiB; బాడీ పది సెకన్లలోపు చేరుకోవాలి. 413 అంటే బాడీ చాలా పెద్దది, 415 అంటే మద్దతు లేని ఫార్మాట్ మరియు 408 అంటే అప్లోడ్ టైమ్ అవుట్ అయ్యింది.
లోపాలు error.code, error.message, వర్తించినప్పుడు ఫీల్డ్ వివరాలు, retryable మరియు request_idను అందిస్తాయి. మద్దతు కోసం X-Request-Idను భద్రపరచండి. 401 అంటే క్రెడెన్షియల్ సమస్య; 403 అంటే అనుమతి సమస్య; 412 అంటే మారిన వెర్షన్; 422 అంటే చెల్లని లేదా సిద్ధంగా లేని కంటెంట్; 428 అంటే అవసరమైన ముందస్తు షరతు లేదు.
429 కోసం Retry-Afterను గౌరవించండి. తాత్కాలిక 503 లేదా నెట్వర్క్ అంతరాయం ఏర్పడితే, అదే కీ మరియు ఇన్పుట్తో పరిమిత బ్యాక్ఆఫ్ ఉపయోగించి మళ్లీ ప్రయత్నించండి. వేరే పేలోడ్కు కొత్త కీ అవసరం. 409 సంభవించినప్పుడు, మునుపటి ఆపరేషన్ను సమన్వయం చేసుకోండి; ఆలోచించకుండా మళ్లీ చేయకండి. దిగుమతులు /jobs/{id} ద్వారా ప్రతి అంశానికి సంబంధించిన ఫలితాలను అందిస్తాయి.
సంతకం చేసిన వెబ్హుక్స్
443 పోర్ట్లో పబ్లిక్ HTTPS రిసీవర్ను ఉపయోగించండి. ఈవెంట్లలో content.review_required, content.published, content.withdrawn, content.publication_failed మరియు import.completed ఉంటాయి. ముడి అభ్యర్థన బాడీని పార్స్ చేయడానికి ముందు దాన్ని ధృవీకరించండి.
HMAC-SHA256(secret, timestamp + "." + event_id + "." + raw_body)
X-Formtruth-Timestamp, X-Formtruth-Event-Id మరియు X-Formtruth-Signatureను చదవండి. ఐదు నిమిషాలకు మించిన టైమ్స్టాంప్లను తిరస్కరించండి. 24 గంటల కీ మార్పిడి సమయంలో సిగ్నేచర్ హెడర్లో కామాలతో వేరు చేయబడిన అనేక v1= విలువలు ఉండవచ్చు; మీరు భద్రపరచిన కీకి సరిపోయే ఏదైనా చెల్లుబాటు అయ్యే సిగ్నేచర్ను అంగీకరించండి.
డూప్లికేషన్ను నివారించడానికి ఈవెంట్ IDని అటామిక్గా భద్రపరచి, పనిని క్యూలో ఉంచి, 2xxను వెంటనే తిరిగి ఇవ్వండి. డెలివరీని మళ్లీ ప్రయత్నించవచ్చు కాబట్టి, డూప్లికేట్ ఈవెంట్ మళ్లీ ప్రచురించకూడదు లేదా రెండుసార్లు ఛార్జ్ చేయకూడదు. సంతకం సీక్రెట్ను API క్రెడెన్షియల్కు వేరుగా ఉంచండి.
కోడ్ ఉదాహరణలు
KnowledgeDocument స్కీమాను మరియు నిజమైన అనుమతించబడిన ట్యాక్సానమీ IDలను ఉపయోగించి document.jsonను సిద్ధం చేయండి. మీ సర్వర్లో FORMTRUTH_API_TOKENను సురక్షితంగా సెట్ చేయండి. ఈ ఉదాహరణలు డ్రాఫ్ట్ను సృష్టిస్తాయి; ప్రచురణకు ఇంకా సమీక్ష వర్క్ఫ్లో అవసరం.
import { readFile } from "node:fs/promises"
import { randomUUID } from "node:crypto"
const base = process.env.FORMTRUTH_URL || "https://www.formtruth.com"
const token = process.env.FORMTRUTH_API_TOKEN
if (!token) throw new Error("Set FORMTRUTH_API_TOKEN in a secure environment")
const document = JSON.parse(await readFile("document.json", "utf8"))
// Persist the key before calling. Reuse it only for an identical retry.
const key = process.env.FORMTRUTH_REQUEST_KEY || randomUUID()
console.log("Request key:", key)
const response = await fetch(base + "/integrations/v1/content/posts", {
method: "POST",
headers: { Authorization: "Bearer " + token, "Content-Type": "application/json", "Idempotency-Key": key },
body: JSON.stringify({ channel: "b2b", external_id: document.locales[document.source_locale].slug, document }),
})
const result = await response.json()
if (!response.ok) throw new Error(JSON.stringify(result.error))
console.log("Draft:", result.entry.id, "ETag:", response.headers.get("etag"))
// Creating a draft does not publish it. Submit for editorial review separately.
import json, os, uuid, urllib.request, urllib.error
base = os.environ.get("FORMTRUTH_URL", "https://www.formtruth.com")
token = os.environ["FORMTRUTH_API_TOKEN"]
with open("document.json", encoding="utf-8") as source:
document = json.load(source)
# Persist this key before sending; reuse for an identical retry.
key = os.environ.get("FORMTRUTH_REQUEST_KEY", str(uuid.uuid4()))
print("Request key:", key)
payload = {"channel": "b2b", "external_id": document["locales"][document["source_locale"]]["slug"], "document": document}
request = urllib.request.Request(base + "/integrations/v1/content/posts",
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), method="POST",
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json", "Idempotency-Key": key})
try:
with urllib.request.urlopen(request, timeout=45) as response:
result = json.load(response)
print("Draft:", result["entry"]["id"], "ETag:", response.headers.get("ETag"))
except urllib.error.HTTPError as error:
raise RuntimeError(error.read().decode("utf-8")) from error
# Creating a draft does not publish it. Submit for editorial review separately.
import { createHmac, timingSafeEqual } from "node:crypto"
export function verifyWebhook(rawBody, headers, secret, now = Date.now()) {
const timestamp = headers.get("x-formtruth-timestamp") || ""
const eventId = headers.get("x-formtruth-event-id") || ""
const signatures = (headers.get("x-formtruth-signature") || "").split(",")
if (!/^[0-9]{10}$/.test(timestamp) || !eventId || Math.abs(now - Number(timestamp) * 1000) > 300000) return false
const expected = createHmac("sha256", secret).update(timestamp + "." + eventId + ".").update(rawBody).digest()
return signatures.some(value => {
const part = value.trim()
if (!/^v1=[a-f0-9]{64}$/.test(part)) return false
const actual = Buffer.from(part.slice(3), "hex")
return actual.length === expected.length && timingSafeEqual(actual, expected)
})
}
// Verify the raw body BEFORE JSON parsing. Atomically record eventId in durable
// storage to deduplicate retries; enqueue accepted work, then return HTTP 2xx.
// During rotation both v1 signatures are sent for 24 hours.
import hashlib, hmac, re, time
def verify_webhook(raw_body, headers, secret, now=None):
timestamp = headers.get("x-formtruth-timestamp", "")
event_id = headers.get("x-formtruth-event-id", "")
signatures = headers.get("x-formtruth-signature", "").split(",")
current = time.time() if now is None else now
if not re.fullmatch(r"[0-9]{10}", timestamp) or not event_id or abs(current - int(timestamp)) > 300:
return False
signed = (timestamp + "." + event_id + ".").encode("utf-8") + raw_body
expected = hmac.new(secret.encode("utf-8"), signed, hashlib.sha256).hexdigest()
return any(re.fullmatch(r"v1=[a-f0-9]{64}", part.strip()) and hmac.compare_digest(part.strip()[3:], expected) for part in signatures)
# Normalize header names to lowercase. Verify raw bytes before parsing JSON.
# Atomically persist event_id for deduplication, enqueue work, then return 2xx.