{"openapi":"3.1.0","info":{"title":"gankdat","version":"0.1.0","description":"Clean-JSON access to UK planning applications, UK procurement notices — one schema across every dataset, from official open-data feeds. Built for developers and AI agents (native MCP + x402). Blind Mode: no personal data is stored or served."},"servers":[{"url":"https://gankdat.com","description":"Production"}],"tags":[{"name":"platform","description":"Health and discovery"},{"name":"data","description":"Dataset query endpoints"}],"paths":{"/v1/health":{"get":{"operationId":"health","summary":"Liveness check","tags":["platform"],"responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"status":{"type":"string"},"version":{"type":"string"}},"required":["status","version"]}},"required":["ok","data"]}}}}}}},"/v1/data":{"get":{"operationId":"list_sources","summary":"List available data sources","tags":["platform"],"responses":{"200":{"description":"Registered sources","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"supported_params":{"type":"array","items":{"type":"string"}},"refresh_cron":{"type":"string"},"credit_cost":{"type":"number"}},"required":["slug","title","description","supported_params","refresh_cron","credit_cost"]}}},"required":["ok","data"]}}}}}}},"/v1/keys":{"post":{"operationId":"create_key","summary":"Issue a free-tier API key (shown once, store it immediately)","tags":["platform"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"name":{"type":"string","maxLength":100}},"required":["email"]}}}},"responses":{"201":{"description":"Key issued — the raw key is never shown again","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"plan":{"type":"string"},"credits":{"type":"number"},"message":{"type":"string"}},"required":["id","key","plan","credits","message"]}},"required":["ok","data"]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Too many keys issued from this IP","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"delete":{"operationId":"revoke_key","summary":"Revoke the presented API key (self-serve)","tags":["platform"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Key revoked","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"revoked":{"type":"boolean"}},"required":["revoked"]}},"required":["ok","data"]}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/usage":{"get":{"operationId":"get_usage","summary":"Current-period credit usage for the presented key (free to call)","tags":["platform"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Usage summary","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"plan":{"type":"string"},"period":{"type":"string"},"used":{"type":"number"},"granted":{"type":"number"},"remaining":{"type":"number"},"alerts":{"type":"array","items":{"type":"string"}}},"required":["plan","period","used","granted","remaining","alerts"]}},"required":["ok","data"]}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/billing/checkout":{"post":{"operationId":"create_checkout","summary":"Create a Stripe Checkout session for a paid plan","tags":["platform"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"}},"required":["plan"]}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}]},"plan":{"type":"string"}},"required":["url","plan"]}},"required":["ok","data"]}}}},"400":{"description":"Unknown plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Billing not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/billing/portal":{"get":{"operationId":"billing_portal","summary":"Get a Stripe customer-portal link (manage/cancel subscription)","tags":["platform"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Portal link","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},"required":["ok","data"]}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"No billing account for this key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Billing not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/waitlist":{"post":{"operationId":"join_waitlist","summary":"Join the launch waitlist (email only, GDPR-minimal)","tags":["platform"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"source":{"type":"string"}},"required":["email"]}}}},"responses":{"200":{"description":"Subscribed (idempotent)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"object","properties":{"subscribed":{"type":"boolean"}},"required":["subscribed"]}},"required":["ok","data"]}}}},"400":{"description":"Invalid request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/data/uk-planning":{"get":{"operationId":"query_uk_planning","summary":"UK planning applications","description":"Planning applications from the official planning.data.gov.uk feed, normalized to one schema. Blind Mode: no applicant personal data.","tags":["data"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"reference","in":"query","required":false,"schema":{"type":"string"}},{"name":"authority","in":"query","required":false,"schema":{"type":"number"}},{"name":"decision_date_after","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"decision_date_before","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"per_page","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Matching UK planning applications records","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"entity":{"type":"number"},"reference":{"type":"string"},"authority":{"type":"number"},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"decision_date":{"anyOf":[{"type":"string"},{"type":"null"}]},"entry_date":{"anyOf":[{"type":"string"},{"type":"null"}]},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}]},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}]},"point":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["entity","reference","authority","description","decision_date","entry_date","start_date","end_date","point"]}},"meta":{"type":"object","properties":{"source":{"type":"string"},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"per_page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_refreshed_at":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["source","page","per_page","total","last_refreshed_at"]}},"required":["ok","data","meta"]}}}},"400":{"description":"Invalid query parameters (see error.details)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Monthly credit quota exhausted (code: quota_exceeded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded (see Retry-After header)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Source temporarily unavailable, retry later","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/data/uk-tenders":{"get":{"operationId":"query_uk_tenders","summary":"UK procurement notices","description":"Public procurement notices from the official Find a Tender OCDS feed, flattened to one queryable schema. Blind Mode: no contact or personal data.","tags":["data"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"buyer","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"procurement_method","in":"query","required":false,"schema":{"type":"string"}},{"name":"cpv_codes","in":"query","required":false,"schema":{"type":"string"}},{"name":"value_amount_min","in":"query","required":false,"schema":{"type":"number"}},{"name":"value_amount_max","in":"query","required":false,"schema":{"type":"number"}},{"name":"published_at_after","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"published_at_before","in":"query","required":false,"schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"per_page","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Matching UK procurement notices records","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"data":{"type":"array","items":{"type":"object","properties":{"ocid":{"type":"string"},"notice_id":{"type":"string"},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}]},"buyer":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"anyOf":[{"type":"string"},{"type":"null"}]},"procurement_method":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"anyOf":[{"type":"string"},{"type":"null"}]},"cpv_codes":{"type":"array","items":{"type":"string"}},"value_amount":{"anyOf":[{"type":"number"},{"type":"null"}]},"value_currency":{"anyOf":[{"type":"string"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"deadline_at":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["ocid","notice_id","title","description","buyer","status","procurement_method","category","cpv_codes","value_amount","value_currency","published_at","deadline_at"]}},"meta":{"type":"object","properties":{"source":{"type":"string"},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"per_page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"last_refreshed_at":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["source","page","per_page","total","last_refreshed_at"]}},"required":["ok","data","meta"]}}}},"400":{"description":"Invalid query parameters (see error.details)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Missing, unknown, or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Monthly credit quota exhausted (code: quota_exceeded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded (see Retry-After header)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Source temporarily unavailable, retry later","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via /v1/keys, sent as a bearer token."}},"schemas":{"ErrorEnvelope":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"object","properties":{"code":{"type":"string","enum":["bad_request","unauthorized","payment_required","quota_exceeded","not_found","rate_limited","unavailable","internal"]},"message":{"type":"string"},"docs_url":{"type":"string"},"details":{}},"required":["code","message","docs_url"]}},"required":["ok","error"]}}}}