The authenticated API surface for projects on the platform. Bearer auth, REST reads + telemetry ingest, five MCP tools registered into Meow AI Engine Pro, plus the AJAX surface that powers the Progression UI.
Every request carries a Bearer token of the form tnz_xxxxxxx.<48-char-secret>. The tnz_xxxxxxx prefix is your public key id (seven hex chars after the prefix). The secret after the dot is shown once when the key is created and never again.
curl -X GET https://tenza.one/wp-json/tenza/v1/projects/123/assessment \
-H "Authorization: Bearer tnz_a1b2c3d.3f4e5d6c7b8a9f0e1d2c3b4a5968778695a4b3c2d1e0f9a8b7c6d5e4f3a2b1c"| Scope | Grants |
|---|---|
read:project | Project post meta + VCS Progression state. |
read:assessment | Full 10-agent assessment JSON + readiness score + evidence tier. |
read:prices | Carbon price feed — all tickers incl. EUA, NGEO, GEO, CCC, CCC-V, ESCERT. |
write:telemetry | POST DePIN telemetry rows to /ingest/telemetry for allow-listed projects. |
mcp | Invoke TenzaOne MCP server read tools from any MCP client. |
/wp-json/tenza/v1/ingest/telemetryscope: write:telemetryAppends a raw telemetry row to wp_tenza_telemetry and updates _tenza_depin_latest_reading on the project for fast reads.
{
"project_id": 123,
"timestamp": "2026-04-22T14:30:00Z",
"readings": {
"generation_kwh": 482.7,
"co2_avoided_tonne": 0.341,
"temperature_c": 68.2
},
"meter_id": "IOT-GW-0042",
"source": "streamr",
"signature": "0x..."
}/wp-json/tenza/v1/projects/{id}/assessmentscope: read:assessmentLatest VCS assessment JSON + readiness score + evidence tier + iteration count.
/wp-json/tenza/v1/projects/{id}/progressionscope: read:projectVCS Progression state — current phase, blockers, last event, next-step copy.
/wp-json/tenza/v1/projects/{id}/telemetry?since=ISO&limit=Nscope: read:projectPaginated telemetry read for a project. Default limit 100, max 1000. Optional since ISO filter.
Primary endpoint: /wp-json/mcp/v1/http — Meow AI Engine Pro's MCP server. The five TenzaOne tools appear under the TenzaOne category alongside Meow's 39 core WP tools in the AI Engine → MCP → Functions panel. Bearer Token comes from AI Engine → Settings → MCP → Bearer Token (not from the TenzaOne → API Keys submenu).
Fallback: sites without AI Engine Pro fall back to the custom JSON-RPC server at /wp-json/tenza/v1/mcp (auth via TenzaOne → API Keys). The custom server auto-disables when Meow's MCP module is active.
| Tool | Returns |
|---|---|
tenza_get_project(id | slug) | Full project post + meta + URL. |
tenza_get_assessment(project_id) | Assessment JSON + readiness + evidence tier. |
tenza_get_progression(project_id) | Current phase + blockers + next step. |
tenza_get_telemetry(project_id, since?, limit?) | Recent DePIN rows for the project. |
tenza_get_prices(symbols?) | Live price feed tickers incl. CCC / CCC-V / ESCERT. |
MCP clients speak stdio JSON-RPC. Drop this 30-line bridge anywhere, set your token, and point Claude Desktop's claude_desktop_config.json at it:
#!/usr/bin/env node
// tenza-mcp-bridge.js
const readline = require('readline');
const https = require('https');
const TOKEN = process.env.TENZA_MCP_TOKEN;
const HOST = process.env.TENZA_MCP_HOST || 'tenza.one';
const rl = readline.createInterface({ input: process.stdin });
rl.on('line', (line) => {
const opts = { hostname: HOST, path: '/wp-json/tenza/v1/mcp', method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${TOKEN}`, 'Content-Length': Buffer.byteLength(line) } };
const req = https.request(opts, (res) => {
let body = '';
res.on('data', (c) => body += c);
res.on('end', () => process.stdout.write(body + '\n'));
});
req.on('error', (e) => process.stdout.write(JSON.stringify({ jsonrpc: '2.0', error: { code: -32603, message: e.message }, id: null }) + '\n'));
req.write(line); req.end();
});// claude_desktop_config.json
{
"mcpServers": {
"tenza-one": {
"command": "node",
"args": ["/path/to/tenza-mcp-bridge.js"],
"env": { "TENZA_MCP_TOKEN": "tnz_xxxxxxx.your-48-char-secret" }
}
}
}The Progression panel + React assessment app drive eleven server actions over /wp-admin/admin-ajax.php. All are nonce-guarded (vcs_processing_nonce or action-specific).
| Action | Role |
|---|---|
tenza_vcs_upload_file | Upload PDF/DOCX/XLSX; returns Meow file_id |
tenza_vcs_run_agent | Invoke one agent (librarian / project_details / methodology / ghg / monitoring / safeguards / auditor / readiness_coach / stakeholder_helper / monitoring_drafter / car_preflight / evidence_chain) |
tenza_vcs_score | Compute readiness score from extracted data |
tenza_vcs_register_project | Create tenza_project CPT from assessment data |
tenza_vcs_update_project | Re-assessment update flow |
tenza_vcs_extract_only / tenza_vcs_register_only | Register-only path (Librarian extract; skip scoring) |
tenza_save_project_coaching | Round 7c · Persist readiness coach output to _tenza_vcs_coaching |
tenza_commit_assessment | Commit project snapshot to Wallet Cert (Ed. 0 / 1.x / 2.x / 3; type-gated) |
tenza_company_extract_url / tenza_company_extract_doc / tenza_company_register | Company (developer) registration pipeline |
{
"summary": "≤30-word next-step sentence",
"blockers": [{ "label": "...", "field": "...", "severity": "critical|high|medium|low", "fix": "..." }],
"gap_fills": [{ "label": "...", "why": "...", "how": "...", "phase_unlocked": "pX_..." }],
"next_actions": [{ "action": "...", "owner_role": "...", "eta_weeks": 0 }],
"phase_recommendation": { "current_best_fit": "pX_...", "evidence": "..." },
"integrity_flags": ["..."]
}{
"p0_scope": { "num": "0", "label": "Scope", "short": "...", "next": "...", "colour": "#22d3ee" },
"p1_design": { "num": "1", "label": "Design & Methodology", "short": "...", "next": "...", "colour": "#22d3ee" },
"p2_pdd": { "num": "2", "label": "PDD Development", ... },
"p3_validate": { "num": "3", "label": "VVB Validation", ... },
"p4_register": { "num": "4", "label": "Verra Registration", ..., "colour": "#4ade80" },
"p5_mrv": { "num": "5", "label": "MRV & Monitoring", ... },
"p6_verify": { "num": "6", "label": "VVB Verification", ... },
"p7_issue": { "num": "7", "label": "VCU Issuance", ..., "colour": "#fbbf24" },
"p8_retire": { "num": "8", "label": "Retire / Trade", ... }
}{
"number_id": "er_baseline_emissions",
"number_label": "Baseline emissions",
"value": 308, "unit": "tCO2e/yr",
"derivation": { "method": "...", "formula_reference": "Equation 3 of AMS-II.C", "calc_cell": "..." },
"source_data_window": { "start_iso": "...", "end_iso": "...", "row_count": 8760, "meter_ids": ["IOT-01"] },
"calibration_refs": [{ "meter_id": "IOT-01", "status": "valid|stale|missing", "cert_file_ref": "..." }],
"hash_payload": "er_baseline_emissions|308|tCO2e/yr|2026-01-01T00:00:00Z|2026-12-31T23:59:59Z|IOT-01|all_valid",
"integrity_status": "complete|partial|broken",
"integrity_notes": ["..."]
}| Code | HTTP | Meaning |
|---|---|---|
tenza_api_no_auth | 401 | Missing Bearer token |
tenza_api_malformed | 401 | Bearer token not tnz_xxx.<secret> shape |
tenza_api_invalid | 401 | Token doesn't match any active key |
tenza_api_revoked | 401 | Key exists but is revoked |
tenza_api_scope | 403 | Scope required by endpoint missing from key |
tenza_api_scope_project | 403 | Key not allow-listed for this project_id |
tenza_api_project_404 | 404 | project_id not a tenza_project post |
tenza_api_rate | 429 | 60 req/min per key exceeded |
tenza_api_db | 500 | DB insert failure on telemetry ingest |
evidence_chain agent) but on-chain anchoring lands in a later round.source field accepts any label; the platform does not yet subscribe to Streamr streams.