← back to Ventura Claw
server/connectors/canva.js
26 lines
// Canva — REAL (Connect API, OAuth Bearer).
const API = "https://api.canva.com/rest/v1";
function token(c) { const t = c?.CANVA_TOKEN || process.env.CANVA_TOKEN; if (!t) throw new Error("CANVA_TOKEN not set"); return t; }
async function call(method, path, body, c) {
const r = await fetch(`${API}${path}`, { method, headers: { "Authorization": `Bearer ${token(c)}`, "Content-Type": "application/json" }, body: body ? JSON.stringify(body) : undefined });
const d = r.status === 204 ? {} : await r.json();
if (!r.ok) throw new Error(`canva ${path} ${r.status}: ${d.message || JSON.stringify(d).slice(0,200)}`);
return d;
}
module.exports = {
meta: { id: "canva", name: "Canva", category: "creative", docsUrl: "https://www.canva.dev/docs/connect/", auth: "oauth2", realImpl: true },
fields: [{ key: "CANVA_TOKEN", label: "Connect API Access Token", type: "password", required: true, hint: "OAuth bearer from canva.dev/docs/connect" }],
configured(c) { return !!(c?.CANVA_TOKEN || process.env.CANVA_TOKEN); },
async health(c) {
if (!this.configured(c)) return { ok: false, reason: "no_token" };
try { const d = await call("GET", "/users/me/profile", null, c); return { ok: true, user: d.profile?.display_name || d.profile?.user_id, account: d.profile?.user_id }; }
catch (e) { return { ok: false, reason: e.message }; }
},
actions: {
async "me"(_, c) { return call("GET", "/users/me/profile", null, c); },
async "designs.list"({ limit }, c) { return call("GET", `/designs?limit=${limit||20}`, null, c); },
async "design.get"({ design_id }, c) { if (!design_id) throw new Error("design_id required"); return call("GET", `/designs/${design_id}`, null, c); },
async "folders.list"(_, c) { return call("GET", "/folders", null, c); }
}
};