{"openapi":"3.0.3","info":{"title":"Kveo Customer API","version":"1.0.0"},"servers":[{"url":"/api/v1"}],"components":{"securitySchemes":{"serviceToken":{"type":"http","scheme":"bearer","bearerFormat":"service-token"}}},"security":[{"serviceToken":[]}],"paths":{"/customer":{"get":{"summary":"Return safe customer profile for the token owner.","responses":{"200":{"description":"Customer profile"},"401":{"description":"Invalid token"}}}},"/services":{"get":{"summary":"List services for the token owner.","responses":{"200":{"description":"Customer services"},"401":{"description":"Invalid token"}}}},"/ai":{"get":{"summary":"Return AI credit and usage status.","description":"Required scope: ai:read. Also returns any credit requests that are still waiting to be handled by Kveo.","responses":{"200":{"description":"AI status"},"401":{"description":"Invalid token"},"403":{"description":"Missing ai:read scope"}}}},"/ai/credit-requests":{"get":{"summary":"List requests for extra AI credit.","description":"Required scope: ai:read. Filter with ?status=pending|approved|rejected.","responses":{"200":{"description":"Credit requests"},"400":{"description":"Invalid status filter"},"401":{"description":"Invalid token"},"403":{"description":"Missing ai:read scope"}}},"post":{"summary":"Ask Kveo to invoice you for extra AI credit.","description":"Required scope: ai:topup. Use this when the AI credit included in your monthly plan is spent. The request does not add credit by itself: Kveo invoices the amount and approves the request, and the credit appears on your balance at that point. Send the same \"reference\" when retrying so a retry never turns into two invoices.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount_nok"],"properties":{"amount_nok":{"type":"number","minimum":100,"maximum":50000,"description":"How much extra credit to be invoiced for, in NOK."},"note":{"type":"string","maxLength":500,"description":"Free text for Kveo, e.g. a purchase order reference."},"reference":{"type":"string","maxLength":120,"description":"Your own idempotency key. Reusing it returns the existing request instead of creating a new one."}}}}}},"responses":{"200":{"description":"A request with the same reference already existed and is returned unchanged"},"201":{"description":"Credit request created and waiting for Kveo"},"400":{"description":"Validation error (amount outside 100–50000 NOK, or note/reference too long)"},"401":{"description":"Invalid token"},"403":{"description":"Missing ai:topup scope or AI not enabled for this customer"},"409":{"description":"Too many pending credit requests already waiting"}}}},"/ai/credit-requests/{id}":{"get":{"summary":"Return one credit request.","description":"Required scope: ai:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Credit request"},"401":{"description":"Invalid token"},"403":{"description":"Missing ai:read scope"},"404":{"description":"Not found for this customer"}}}},"/ai/messages":{"post":{"summary":"Send a message to Claude (Anthropic) through Kveo's AI gateway.","description":"Required scope: ai:use. The model is fixed per customer by Kveo and cannot be chosen in the request. Mirrors the shape of Anthropic's own Messages API.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"type":"object"},"description":"Same shape as the Anthropic Messages API messages array."},"system":{"type":"string"},"max_tokens":{"type":"integer","minimum":1}}}}}},"responses":{"201":{"description":"Message created"},"400":{"description":"Validation error"},"401":{"description":"Invalid token"},"402":{"description":"The AI credit for this month is used up — ask for more with POST /ai/credit-requests"},"403":{"description":"Missing ai:use scope, AI not enabled for this customer, or no key configured"},"502":{"description":"The upstream Anthropic API rejected or failed the request"}}}},"/invoices":{"get":{"summary":"List invoices visible to this customer.","description":"Required scope: invoices:read","responses":{"200":{"description":"Invoices"},"401":{"description":"Invalid token"},"403":{"description":"Missing invoices:read scope"}}}},"/support/tickets":{"get":{"summary":"List support tickets for this customer.","description":"Required scope: support:read","responses":{"200":{"description":"Support tickets"},"401":{"description":"Invalid token"},"403":{"description":"Missing support:read scope"}}},"post":{"summary":"Create a support ticket for this customer.","description":"Required scope: support:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","body"],"properties":{"title":{"type":"string","maxLength":160},"body":{"type":"string","maxLength":5000},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"service_id":{"type":"integer"},"resource_type":{"type":"string"},"resource_id":{"type":"string"}}}}}},"responses":{"201":{"description":"Ticket created"},"400":{"description":"Validation error"},"401":{"description":"Invalid token"},"403":{"description":"Missing support:write scope"},"404":{"description":"Service not found for this customer"}}}},"/sms/send":{"post":{"summary":"Send an SMS through Kveo's SMS gateway using your configured sender ID.","description":"Required scope: sms:send. The sender ID is fixed per customer by Kveo and cannot be overridden in the request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","message"],"properties":{"to":{"type":"string","description":"Recipient in international format, e.g. +4712345678","example":"+4712345678"},"message":{"type":"string","maxLength":918}}}}}},"responses":{"201":{"description":"SMS accepted by the gateway"},"400":{"description":"Validation error"},"401":{"description":"Invalid token"},"403":{"description":"Missing sms:send scope, or SMS not enabled for this customer"},"502":{"description":"The upstream SMS gateway rejected or failed the request"}}}},"/sms/log":{"get":{"summary":"List recent SMS sent through the gateway for this customer.","description":"Required scope: sms:read","responses":{"200":{"description":"SMS send log"},"401":{"description":"Invalid token"},"403":{"description":"Missing sms:read scope"}}}},"/status":{"get":{"summary":"Return service status for this customer.","description":"Required scope: status:read","responses":{"200":{"description":"Service statuses"},"401":{"description":"Invalid token"},"403":{"description":"Missing status:read scope"}}}}}}