Yatabase API reference
Single-host BaaS combining a real-time graph database (Cypher / SPARQL),
S3-style object storage, an MCP tool surface, and AT Protocol-native auth.
Every section below is copy-pastable curl that targets https://yatabase.gftd.ai.
# TypeScript types (openapi-typescript) npx openapi-typescript https://yatabase.gftd.ai/openapi.json -o yatabase.d.ts # Generate a Python client (openapi-python-client) openapi-python-client generate --url https://yatabase.gftd.ai/openapi.json
Quickstart
From zero to first row in 30 seconds:
# 1. Sign up — anonymous mint, returns sk_live_yata_* SIGNUP=$(curl -sS -X POST https://yatabase.gftd.ai/auth/v1/signup) KEY=$(echo "$SIGNUP" | python3 -c 'import sys,json;print(json.load(sys.stdin)["apiKey"])') echo "$KEY" # 2. Create a vertex curl -X POST https://yatabase.gftd.ai/cypher \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"query":"CREATE (n:Demo {name:\"hello\"}) RETURN n"}' # 3. Query it back curl -X POST https://yatabase.gftd.ai/cypher \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"query":"MATCH (n:Demo) RETURN n.name LIMIT 10"}'
The signup response also contains orgDid (e.g. did:web:t-xxxxx.yata-tenant.gftd.ai),
a fresh AWS access-key pair, and an emailStatus field if you passed {email, name}.
Auth
Three accepted token shapes on the Authorization header:
| Token | Mints via | Use |
|---|---|---|
Bearer sk_live_yata_* | POST /auth/v1/signup | Default. Per-tenant scope. |
Bearer sk_live_* | ai.gftd.auth.createApiKey | Cross-product key. |
| AT Protocol JWT | com.atproto.server.getSession | For atproto-native clients. |
All authenticated calls also accept X-Active-DID to disambiguate when the caller controls multiple path-based DIDs.
Cypher (graph)
POST /cypher — Neo4j HTTP-shape compatible subset on RisingWave.
Supported:
MATCH (n:Label) [WHERE prop OP val [(AND|OR) ...]] RETURN n[.prop] [AS alias] [, ...][ORDER BY n.prop ASC|DESC] [SKIP N] [LIMIT N]CREATE (n:Label {k: v, ...}) [RETURN ...]MATCH (n:Label {pk: v}) SET n.prop = expr [, ...]MATCH (n:Label {pk: v}) DELETE nMATCH (a:L1)-[:R]->(b:L2) [WHERE ...] RETURN ...MATCH (a:L1{pk:v}),(b:L2{pk:v}) CREATE (a)-[:R]->(b)
Forbidden at the edge: DETACH DELETE, FOREACH, CALL { ... write ... }.
Deferred: multi-hop, variable-length path, MERGE, count()/collect(), OPTIONAL MATCH, WITH.
# Edge traversal curl -X POST https://yatabase.gftd.ai/cypher \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"query":"MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name LIMIT 25"}'
Response shape (Neo4j HTTP API compatible):
{
"results": [{ "columns": ["a.name","b.name"], "data": [["alice","bob"]] }],
"errors": []
}
SPARQL
POST /sparql — SPARQL 1.1 SELECT / CONSTRUCT / ASK on the same graph.
curl -X POST https://yatabase.gftd.ai/sparql \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/sparql-query' \ --data 'SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 10'
Storage REST (Supabase shape)
S3-compatible blob store. PUT/GET/HEAD/DELETE on /storage/v1/object/{bucket}/{key}.
# Upload curl -X PUT --data-binary @photo.jpg \ -H "authorization: Bearer $KEY" \ https://yatabase.gftd.ai/storage/v1/object/my-bucket/photo.jpg # List bucket curl -H "authorization: Bearer $KEY" \ https://yatabase.gftd.ai/storage/v1/object/list/my-bucket # Public download (only if bucket public_read=true AND ACL grants it) curl https://yatabase.gftd.ai/storage/v1/object/public/my-bucket/photo.jpg # Presigned URL curl -X POST -H "authorization: Bearer $KEY" \ https://yatabase.gftd.ai/storage/v1/object/sign/my-bucket/photo.jpg
S3 SigV4 compat
Same blobs, AWS SigV4 wire format. Use the awsAccessKeyId + awsSecretAccessKey returned by /auth/v1/signup.
aws --endpoint-url https://yatabase.gftd.ai/s3 \
s3 cp photo.jpg s3://my-bucket/photo.jpg
MCP (JSON-RPC 2.0)
Every yatabase surface is also an MCP tool. POST /mcp.
initialize / ping / tools/list / resources/list / prompts/list are public.
tools/call and resources/read require auth.
# List tools (public) curl -X POST https://yatabase.gftd.ai/mcp \ -H 'content-type: application/json' \ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}' # Call yata.graph.cypher curl -X POST https://yatabase.gftd.ai/mcp \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"yata.graph.cypher","arguments":{"query":"MATCH (n) RETURN n LIMIT 5"}},"id":2}'
Discovery doc: /.well-known/mcp.json.
XRPC pass-through
Native AT Protocol XRPC for ai.gftd.apps.yata.* and ai.gftd.apps.billing.*.
curl -X POST https://yatabase.gftd.ai/xrpc/ai.gftd.apps.yata.runCypher \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"query":"MATCH (n:Demo) RETURN n LIMIT 10"}'
Plans & quotas
USD-primary pricing, JPY-secondary (FX 150 JPY/USD).
| Plan | USD/mo | JPY/mo | API req / day | Storage | Cypher CU-h / day |
|---|---|---|---|---|---|
| Free | $0 | ¥0 | 1,000 | 5 GB | 5 |
| Starter | $13 | ¥1,950 | 33,333 | 50 GB | 50 |
| Developer | $33 | ¥4,950 | 333,333 | 500 GB | 500 |
| Business | $650 | ¥97,500 | 33M | 5 TB | 5,000 |
| Enterprise | $6,700+ | ¥1.005M+ | unlimited | unlimited | unlimited |
Quota check is per-day, sums today's api_request billing events. Hit 429 with Retry-After when exceeded.
Read your usage:
curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/api/usage curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/api/plan
Upgrade
curl -X POST https://yatabase.gftd.ai/auth/v1/upgrade \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{"plan":"starter"}'
Returns {checkoutUrl, sessionId} when Stripe is wired (live since 2026-05-10).
Open checkoutUrl to complete payment. Stripe webhook then flips the plan tier
inside ~40 s of payment confirmation.
Customer portal (change card, cancel, view invoices)
curl -X POST https://yatabase.gftd.ai/auth/v1/portal \ -H "authorization: Bearer $KEY" \ -d '{}'
Returns {portalUrl} — a Stripe-hosted page where customers self-serve
billing (update card, cancel subscription, download past invoices). Requires the
org has completed at least one Checkout (400 NoStripeCustomer on free).
Key recovery (lost your API key?)
Anonymous signup is convenient but losing the key would normally orphan the tenant. Attach a recovery email before you need it. Attaching emails a 24-hour verification link — you must click it before recovery works (this prevents an attacker from attaching a victim's email and abusing yatabase to send them spam-looking "recovery" notices):
# 1a. Attach an email while you still have the key (emails a verify link) curl -X POST https://yatabase.gftd.ai/auth/v1/attach-email \ -H "authorization: Bearer $KEY" \ -d '{"email":"you@example.com"}' # 1b. Click the verification link in your inbox. The link calls: # GET /auth/v1/verify-email?token=... (24-hour TTL, single-use) # Confirm with: curl https://yatabase.gftd.ai/auth/v1/whoami -H "authorization: Bearer $KEY" # attachedEmailVerified should now be true. # 2. Later, if you lose the key, anyone can request a recovery link curl -X POST https://yatabase.gftd.ai/auth/v1/recover \ -d '{"email":"you@example.com"}' # Always returns 200 (no enumeration leak). If the email matches a # tenant, a recovery link is sent. Link contains a 48-hex token with # a 15-minute TTL. # 3. Click the link → it posts the token to /auth/v1/redeem and # returns a brand-new API key for the matching org. curl -X POST https://yatabase.gftd.ai/auth/v1/redeem \ -d '{"token":"...48 hex chars from the link..."}'
Existing keys remain valid after recovery — recovery is additive, not replacement.
Revoke the lost key separately via /auth/v1/revoke once the new key is in hand.
Who am I?
curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/auth/v1/whoami
Returns the tenant identity for the current bearer:
{orgDid, actorDid, plan, attachedEmail, stripeCustomerId, canOpenPortal}.
Useful for client bootstrap, dashboard rendering, and confirming a recovered key
resolved to the original tenant.
Members & multi-tenant
# List members of your org curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/api/members # Mint a new key for a teammate curl -X POST https://yatabase.gftd.ai/auth/v1/invite \ -H "authorization: Bearer $KEY" \ -d '{"name":"alice"}' # Revoke a key curl -X POST https://yatabase.gftd.ai/auth/v1/revoke \ -H "authorization: Bearer $KEY" \ -d '{"vertex_id":"apikey:..."}'
Outbound webhooks
Register a URL to receive HMAC-signed POST notifications when Cypher mutations happen. Useful for replicating to Slack, Zapier, your own backend, or any HTTP endpoint.
# Register a webhook (URL must be HTTPS) curl -X POST https://yatabase.gftd.ai/api/webhooks \ -H "authorization: Bearer $KEY" \ -H 'content-type: application/json' \ -d '{ "url": "https://your-app.example.com/yata-webhook", "label": "Person", "types": ["cypher.create", "cypher.set", "cypher.delete"] }' # Response includes webhook.secret — save it. Subsequent GETs only show secretPrefix. # List your webhooks (secret redacted) curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/api/webhooks # Remove a webhook curl -X DELETE https://yatabase.gftd.ai/api/webhooks/whk_... \ -H "authorization: Bearer $KEY"
| Event | Fires on | Payload |
|---|---|---|
cypher.create | CREATE (n:Label {…}) | {label, properties} |
cypher.set | MATCH … SET n.x = "y" | {label, properties, updatedCount} |
cypher.delete | MATCH (n:Label) DELETE n | {label, deletedCount} |
cypher.create_edge | CREATE (a)-[:T]->(b) | {srcLabel, srcProperties, edgeType, edgeProperties, dstLabel, dstProperties} |
cypher.delete_edge | MATCH (a)-[r:T]->(b) DELETE r | {srcLabel, edgeType, dstLabel} |
Delivery contract
- Method:
POST application/json - X-Yatabase-Event: the event name (e.g.
cypher.create) - X-Yatabase-Signature:
hex(hmac-sha256(secret, body))— verify in your handler to authenticate the call - X-Yatabase-Delivery: nanoid for tracing / dedup
- Body:
{event, orgDid, ...payload, ts} - Retries: fire-and-forget in v1. The next matching mutation will re-fire — design your handler idempotent if you care about exactly-once.
- Per-org cap: 10 webhooks.
DELETEone before adding another. - HTTPS only:
http://URLs are rejected at registration.
Verifying a delivery (Node example)
import crypto from "node:crypto";
function verifyYatabase(req, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(req.rawBody) // the exact bytes received
.digest("hex");
return req.headers["x-yatabase-signature"] === expected;
}
Data rights (CCPA / GDPR / 改正個人情報保護法)
# Right to know — full export curl -H "authorization: Bearer $KEY" https://yatabase.gftd.ai/api/export # Right to delete — irreversible curl -X POST https://yatabase.gftd.ai/api/account/delete \ -H "authorization: Bearer $KEY" \ -d '{"confirm":"DELETE"}'
See /.well-known/agent.json for the legal disclaimer.
Billing rows (vertex_billing_event) are retained 7 years per 法人税法 §126 / IRS §6001.
Errors
| Status | Body shape | When |
|---|---|---|
| 400 | {error,message} | Bad JSON / forbidden Cypher / invalid params |
| 401 | {error:"Unauthorized"} | Missing / invalid Bearer |
| 403 | {error:"Forbidden"} | Admin gate (operator-only paths) |
| 404 | {error:"NotFound"} | Path / resource missing |
| 409 | {error:"PreconditionFailed"} | State machine violation |
| 429 | {error:"QuotaExceeded"} | Daily plan cap hit; Retry-After header set |
| 500 | {error:"InternalServerError"} | Worker exception |
| 503 | {error:"ServiceUnavailable"} | Hyperdrive / dispatcher unreachable |
Observability
/health— Worker probe (always JSON ok:true)/_app/meta— version + surface listing/status— public uptime + 7d agent activity/team— 4 resident AI actors with public DIDs/api/audit(auth) — last 90 d of your tenant's request log/api/outbox(auth) — your tenant's email outbox/api/invoices(auth) — month list;/api/invoice?month=YYYY-MMfor HTML
Compliance
| Regulation | Article | Endpoint |
|---|---|---|
| CCPA | §1798.100 (right to know) | GET /api/export |
| CCPA | §1798.105 (right to delete) | POST /api/account/delete |
| GDPR | Art 17 (erasure) | POST /api/account/delete |
| GDPR | Art 20 (portability) | GET /api/export |
| GDPR | Art 30 (records of processing) | vertex_audit_log (90 d) |
| 改正個人情報保護法 | 第33条 (開示請求) | GET /api/export |
| 改正個人情報保護法 | 第34-36条 (削除請求) | POST /api/account/delete |
| JP 適格請求書 (T9007028460042) | etz hayim | GET /api/invoice?month=YYYY-MM |
| 法人税法 | §126 (7 y retention) | vertex_billing_event |
| IRS | §6001 (7 y retention) | same |
Operator: etz hayim (運営法人). Vendor: Gftd Japan株式会社 (T9007028460042).