{"openapi":"3.1.0","info":{"title":"Soulfy Agent API","version":"1.0.0","description":"Lets a customer's Grok Bot send social media snapshots to their Soulfy workspace and, with the owner's permission, prepare the Growth Actions the owner sends it. Send one snapshot per platform after each daily stats check. Once a day is plenty; the Board shows change over days and weeks."},"externalDocs":{"url":"https://soulfy.com/docs/grok-bot"},"servers":[{"url":"https://soulfy.com/api/agent/v1"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Credential starting with sfa_."}},"schemas":{"Error":{"type":"object","required":["success","code","error"],"properties":{"success":{"const":false},"code":{"type":"string"},"error":{"type":"string"}}},"Measurement":{"type":"object","required":["platform","captured_at","metrics"],"additionalProperties":false,"properties":{"platform":{"type":"string","enum":["instagram","facebook","linkedin","tiktok","youtube","x"]},"captured_at":{"type":"string","format":"date-time","description":"ISO 8601 with a timezone."},"metrics":{"type":"object","maxProperties":50,"propertyNames":{"pattern":"^[a-z][a-z0-9_]*$"},"additionalProperties":{"type":"number"},"description":"Recommended names: estimated_earnings, fan_support_earnings, subscription_earnings, bonus_earnings, ad_earnings, followers, reach, impressions, views, likes, comments, shares, saves, posts, profile_visits, link_clicks, content_monetization_earnings, reactions, videos, subscribers, publishing_frequency, website_visits, leads, inquiries, contacts, conversions, customers, revenue, sales_value. Other names are saved but not charted, and produce a warning."},"collection_method":{"type":"string","enum":["browser_agent","platform_export","manual_entry","other"],"default":"browser_agent"},"source":{"type":"object","additionalProperties":{"type":"string"},"description":"Flat strings. With earnings metrics, send currency (ISO 4217, e.g. USD) and earnings_period (e.g. last_28_days)."},"evidence":{"type":"object","additionalProperties":{"type":"string"}},"workspace":{"type":"string","description":"Your site domain. Optional; must match the credential."}},"example":{"platform":"facebook","captured_at":"2026-09-29T21:10:00+08:00","metrics":{"estimated_earnings":125.4,"content_monetization_earnings":98.1,"followers":5517,"reach":4001,"reactions":46,"comments":15,"shares":15},"source":{"currency":"USD","earnings_period":"last_28_days"}}},"GrowthResult":{"type":"object","required":["result_type"],"additionalProperties":false,"properties":{"result_type":{"type":"string","enum":["draft","text","checklist","external_reference","artifact","status"]},"data":{"type":"object","description":"Up to 64 KB of JSON, e.g. {\"text\": \"…\"}. Never credentials."},"summary":{"type":"string","maxLength":1000}}}}},"paths":{"/connect":{"post":{"summary":"Exchange a one-time connect code for a credential","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","pattern":"^sfc_"}}}}}},"responses":{"201":{"description":"Connected. Store token as SOULFY_AGENT_TOKEN; it is shown only once.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"const":true},"token":{"type":"string"},"workspace":{"type":"object"},"scopes":{"type":"array","items":{"type":"string","enum":["brand.read","ibrand.read","content.read","measurements.write","drafts.write","growth.execute","social.publish","social.reply","email.send"]}},"expires_at":{"type":["string","null"],"format":"date-time"},"endpoints":{"type":"object"},"instructions":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Invalid, used or expired connect code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many failed attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me":{"get":{"summary":"Check the credential","security":[{"bearer":[]}],"responses":{"200":{"description":"Workspace, permissions and expiry."},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurements":{"post":{"summary":"Send one social media snapshot","security":[{"bearer":[]}],"parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean"},"description":"Validate and return what would be stored, without saving."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Measurement"}}}},"responses":{"200":{"description":"Idempotent replay, or a dry run (dry_run: true, nothing saved)."},"201":{"description":"Stored.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"const":true},"measurement_id":{"type":"string"},"platform":{"type":"string"},"captured_at":{"type":"string","format":"date-time"},"received_at":{"type":"string","format":"date-time"},"idempotent_replay":{"type":"boolean"},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"const":"unknown_metric"},"metric":{"type":"string"},"suggestion":{"type":["string","null"]},"message":{"type":"string"}}}}}}}}},"400":{"description":"Invalid body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing permission, wrong workspace, or site not on its own domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused for different data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Body too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type isn't application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs":{"get":{"summary":"Growth Actions you're running or waiting on, then the owner's queue (oldest first). Poll no more than every 30 seconds.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"responses":{"200":{"description":"OK: success, jobs[], poll_after_seconds."},"201":{"description":"Created (results, questions): success, jobs[], poll_after_seconds."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"A job's instructions, execution_rules, action, focus, goal, niche, topic, status and the owner's answers to your questions. niche and topic are null when the owner hasn't set them.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"responses":{"200":{"description":"OK: success, job."},"201":{"description":"Created (results, questions): success, job."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/claim":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Claim a queued job. It is yours for 30 minutes; renew with heartbeat.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"responses":{"200":{"description":"OK: success, job."},"201":{"description":"Created (results, questions): success, job."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/heartbeat":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Keep a running job claimed for another 30 minutes.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"responses":{"200":{"description":"OK: success, status, lease_expires_at."},"201":{"description":"Created (results, questions): success, status, lease_expires_at."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/results":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Add a result to a running job. Results can't be changed later.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrowthResult"}}}},"responses":{"200":{"description":"OK: success, result."},"201":{"description":"Created (results, questions): success, result."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/questions":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Ask the owner a question. The job waits until they answer; then GET the job.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["input_type","prompt"],"additionalProperties":false,"properties":{"input_type":{"type":"string","enum":["text","choice","confirm"]},"prompt":{"type":"string","maxLength":1000},"options":{"type":"array","items":{"type":"string"},"minItems":2,"maxItems":10,"description":"Required for choice."}}}}}},"responses":{"200":{"description":"OK: success, status, question."},"201":{"description":"Created (results, questions): success, status, question."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/complete":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Finish a running job, optionally with one last result.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"result":{"$ref":"#/components/schemas/GrowthResult"}}}}}},"responses":{"200":{"description":"OK: success, status, completed_at."},"201":{"description":"Created (results, questions): success, status, completed_at."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/growth/jobs/{id}/fail":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"summary":"Stop a running job with a short reason the owner will see.","description":"Needs the growth.execute permission (Run Growth Actions). Never publishes or sends anything.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reason"],"additionalProperties":false,"properties":{"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"OK: success, status, failed_at."},"201":{"description":"Created (results, questions): success, status, failed_at."},"400":{"description":"Invalid body or unknown field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing growth.execute, or another connection claimed the job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such job for this workspace, or it isn't queued or yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The job's status doesn't allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}