Developers
TRVUE API v1
Programmatic access to the launch platform: discover campaigns, read funding stats and verification evidence, pledge support, and post updates — the same API the TRVUE app runs on.
Quickstart
Reads need no key to start — the public demo key is applied automatically, with a limit of 30 requests per minute. Production keys are issued per tier.
curl "https://trvue.com/api/v1/launches"{
"data": {
"count": 8,
"launches": [
{ "slug": "harbor-roastery", "title": "Harbor Roastery — Second Location",
"tagline": "A community-owned café on the waterfront",
"category": "location", "status": "live",
"company": { "id": "cmp_01", "name": "Harbor Roastery", "status": "verified" },
"goalUsd": 120000, "raisedUsd": 87420, "pctFunded": 72.9,
"supporters": 341, "daysRemaining": 12, "deadline": "2026-10-02T00:00:00.000Z",
"token": { "ticker": "HRBR", "mode": "new" }, "featured": true },
…
]
},
"meta": { "version": "v1", "engine": "trvue-engine-1.0.0", "at": "2026-09-05T09:00:00.000Z" }
}Add ?slug=harbor-roastery for the full bundle: the launch record (story, support tiers, milestones, utility rules, disclosures), the derived stats, the five-line Verified Launch checklist, and the company.
Endpoints
| Method | Path · Auth | Description |
|---|---|---|
| GET | /api/v1/launchesAPI key | List launches as card projections: title, company, status, funding stats, token ticker. |
| GET | /api/v1/launches?slug={slug}API key | Full campaign bundle: launch record, derived stats, Verified Launch checklist, company, linked token project. |
| POST | /api/v1/launchessession + CSRF | Create a launch (story, tiers, milestones, token). New launches enter verification review. |
| POST | /api/v1/launches/{slug}/supportsession + CSRF | Pledge support to a live campaign — a tier or a custom amount. |
| POST | /api/v1/launches/{slug}/commentssession + CSRF | Post a community comment on a campaign. |
| POST | /api/v1/launches/{slug}/updatessession + CSRF · owner/admin | Post a campaign progress update — supporters are notified. |
| POST | /api/v1/launches/{slug}/settlesession + CSRF · admin | Goal-miss settlement: refund every paid pledge of an ended campaign (idempotent). |
| GET | /api/v1/followssession | Company ids the signed-in account follows — a relationship, not a cookie. |
| POST / DELETE | /api/v1/followssession + CSRF | Follow or unfollow a company by { companyId }. |
| GET / POST | /api/v1/waitlistAPI key | Marketplace waitlist: public signup count, and join with { email, interest }. |
Companion endpoints follow the same conventions: /api/v1/companies (register and list, plus domain verification via a DNS record), the owner-only /launches/{slug}/edit and /cancel, and the anonymous view/share beacon /launches/{slug}/track (rate limited per IP, no viewer data stored).
Response envelope & tracing
Every response is enveloped. Success wraps the payload in data alongside a meta block; errors return a machine code and a human message:
{ "data": { … }, "meta": { "version": "v1", "engine": "trvue-engine-1.0.0", "at": "<ISO timestamp>" } }
{ "error": { "code": "not_found", "message": "No launch with slug 'harbor-roastery'." } }Every request is traced: the x-trvue-request-id response header carries a stable id you can quote in a support request. Common error codes: 400 invalid_json/invalid_body, 401 auth_required/invalid_api_key, 403 forbidden/csrf_failed, 404 not_found, 422 for rejected domain writes, and 429 rate_limited.
Authentication & rate limits
Auth has two layers. Reads use tiered API keys for rate limiting. Mutations additionally require a signed-in session and CSRF proof: send the value of the trvue_csrf cookie back in the x-trvue-csrf header (double submit; the track beacon is the documented exception).
| Tier | Header | Limit |
|---|---|---|
| Public demo | none / trvue_demo | 30 req/min |
| Verified partner | Authorization: Bearer trvue_sk_live_… | 120 req/min |
| Institutional | Authorization: Bearer trvue_sk_live_… | 600 req/min |
Responses include the X-RateLimit-Remaining, X-RateLimit-Reset and X-TRVUE-Tier headers.
Pledge support
Send a tierId or a custom amountUsd. With payments configured, the response is a Stripe Checkout redirect and the pledge stays pending until the signed webhook confirms it; without payments, the pledge records support intent directly.
curl -X POST https://trvue.com/api/v1/launches/harbor-roastery/support \
-H "Content-Type: application/json" \
-H "Cookie: trvue_session=<session>; trvue_csrf=<token>" \
-H "x-trvue-csrf: <token>" \
-d '{ "tierId": "tr_2" }'{
"data": {
"pledge": { "id": "plg_9b1d40e2a6c5", "amountUsd": 250, "tokens": 500,
"tierId": "tr_2", "createdAt": "2026-09-05T09:12:44.000Z", "status": "demo" }
},
"meta": { … }
}
// Real-money path instead returns:
{ "data": { "checkoutUrl": "https://checkout.stripe.com/…", "pledgeId": "plg_9b1d40e2a6c5", "status": "pending" } }Create a launch
A launch belongs to the company the signed-in user is a member of — register one first via POST /api/v1/companies, or you get 403 company_required. Input is validated, including the financial-instrument language guard: campaign copy presenting the token as equity, shares, dividends or promised returns is rejected.
curl -X POST https://trvue.com/api/v1/launches \
-H "Content-Type: application/json" \
-H "Cookie: trvue_session=<session>; trvue_csrf=<token>" \
-H "x-trvue-csrf: <token>" \
-d '{
"title": "Harbor Roastery — Second Location",
"tagline": "A community-owned café on the waterfront",
"description": "…",
"category": "location",
"story": { "problem": "…", "building": "…", "why": "…" },
"goalUsd": 120000,
"durationDays": 30,
"milestones": [ { "amountUsd": 60000, "title": "Lease signed" } ],
"tiers": [ { "title": "Founding Regular", "amountUsd": 50, "tokens": 100,
"benefits": ["Launch-day tasting invite"] } ],
"token": { "mode": "new", "name": "Harbor Token", "ticker": "HRBR", "chain": "base",
"totalSupply": 10000000, "launchAllocation": 2400000,
"utilitySummary": "Membership, discounts and event access" },
"utilityRules": [ { "kind": "discount", "minTokens": 500, "label": "10% off every order" } ]
}'
// → { "data": { "slug": "harbor-roastery-second-location", "id": "lch_4f2a91c30b77", "status": "verification" } }Campaign lifecycle
draft → verification → scheduled → live → funded | ended | cancelledCreated launches enter verification; an admin approval moves them live with a fresh campaign window, so review time never eats into the campaign. Time-based transitions are derived at read time — a live campaign past its deadline reads as funded or ended — and funding totals are always recomputed from pledge records, never trusted from a stored row. Funded and ended campaigns are immutable; goal-miss settlement refunds every paid pledge via /settle.
Trust-to-Access
Gate your own product on TRVUE evidence. evaluatePolicy in @/lib/sdk/trvue-client takes a policy, reads live verification data, and returns an allow/deny with the reasons behind it — so you can refuse a listing, a pool, or an integration on stated grounds rather than a hunch.
const decision = await evaluatePolicy(client, "meridian", {
minScore: 70,
minTier: "verified",
requireNoOpenViolations: true,
allowedChains: ["ethereum", "base"],
});
// { allowed, reasons: string[], summary }| Field | Requires |
|---|---|
| minScore | Total Trust Score at or above this value (0–100). Defaults to 70. |
| minTier | Verification tier at or above basic, verified, protected or institutional. |
| requireNoOpenViolations | No open promise violations against the project. |
| minContractScore | Smart-contract factor score at or above this value. |
| minLiquidityScore | Liquidity-security factor score at or above this value. |
| allowedChains | The project's chain is one your platform supports. |
Every gate fails closed. A requirement whose evidence is missing — a failed lookup, an absent project, a factor not present in the payload — denies and names the missing input. A configured gate is never silently waived.
Webhooks
Monitoring events are POSTed to your endpoint as JSON, signed with X-TRVUE-Signature and labelled with X-TRVUE-Event.
X-TRVUE-Event: promise-violation
X-TRVUE-Signature: t=1788920000,v1=<64 hex chars>
{"id":"ev_…","type":"promise-violation","severity":"critical",
"title":"…","body":"…","project":{"slug":"meridian"},
"actionUrl":"…","sentAt":"2026-09-09T14:00:00.000Z"}Verify before you trust: the signature is t=<unix>,v1=HMAC_SHA256(`${t}.${body}`), and stamps outside a 600s window are rejected as replays. Compare in constant time.
Delivery is retried three times with backoff and an 8-second timeout per attempt; a non-2xx response counts as a failure. Send yourself a signed sample with POST /api/v1/webhooks/test.