{"openapi":"3.1.0","info":{"title":"UIDWatch API","version":"1.0.0","description":"Bankruptcy, liquidation, deletion and register change alerts from the Swiss Official Gazette of Commerce for a watchlist of Swiss company UIDs. Errors are always {\"error\":{\"code\",\"message\",\"details\"?}}. Using the API means accepting https://uidwatch.tollwyn.com/terms."},"servers":[{"url":"https://uidwatch.tollwyn.com"}],"security":[{"apiKey":[]}],"paths":{"/api/v1/signup":{"post":{"operationId":"signUp","summary":"Create an account and get an API key at once (accepts the terms)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","accept_terms"],"properties":{"email":{"type":"string","format":"email","maxLength":254},"via":{"type":"string","description":"Optional partner id: lower-case words joined by hyphens"},"accept_terms":{"type":"boolean","const":true,"description":"Accepts the terms at https://uidwatch.tollwyn.com/terms, including the data processing terms in section 8, on behalf of the business that signs up."}}}}}},"responses":{"201":{"description":"The account in its trial and its first API key (shown only here). The trial allows 20 entries until a person confirms the email address.","content":{"application/json":{"schema":{"type":"object","required":["api_key","account"],"properties":{"api_key":{"type":"string"},"account":{"$ref":"#/components/schemas/Account"}}}}}},"400":{"description":"The body is not JSON (invalid_json).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"An account with this email exists (email_taken).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The body is not valid, for example accept_terms is not true (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/account":{"get":{"operationId":"getAccount","summary":"Plan, limit, usage and the last check of the gazette","responses":{"200":{"description":"The account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/watchlist":{"get":{"operationId":"listWatchlist","summary":"List the watchlist, oldest entry first","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":100}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"group","in":"query","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"A page of entries.","content":{"application/json":{"schema":{"type":"object","required":["items","total","limit","offset"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WatchEntry"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"limit, offset or group is not valid (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"addToWatchlist","summary":"Add entries or change their reference (all or nothing)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchInput"}}}},"responses":{"200":{"description":"What changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeSummary"}}}},"400":{"description":"The body is not JSON (invalid_json).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The plan does not allow that many entries (limit_exceeded; details: limit, needed, missing) or monitoring is paused (monitoring_paused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is larger than 10 MB (payload_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Some UIDs are not valid (invalid_uid; details list every one) or the body is not valid (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"replaceWatchlist","summary":"Replace the whole watchlist (all or nothing), e.g. a nightly ERP sync","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchInput"}}}},"responses":{"200":{"description":"What changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeSummary"}}}},"400":{"description":"The body is not JSON (invalid_json).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The plan does not allow that many entries or monitoring is paused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The body is larger than 10 MB (payload_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Some UIDs are not valid (invalid_uid) or the body is not valid (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/watchlist/{uid}":{"delete":{"operationId":"removeFromWatchlist","summary":"Remove an entry","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"string","maxLength":40,"example":"CHE-110.090.028"}},{"name":"group","in":"query","schema":{"type":"string","maxLength":100,"default":""}}],"responses":{"204":{"description":"Removed."},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on the list in this group (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Not a valid UID (invalid_uid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events":{"get":{"operationId":"listEvents","summary":"Events after a cursor, oldest first","description":"Keep next_cursor and ask again with it: every event comes exactly once.","parameters":[{"name":"cursor","in":"query","schema":{"type":"string","pattern":"^\\d{1,18}$","default":"0"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"kind","in":"query","schema":{"type":"string","enum":["bankruptcy","composition","debt_enforcement","liquidation","deletion","deficiency","change","new_entry"]}},{"name":"historical","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"uid","in":"query","schema":{"type":"string","maxLength":40}},{"name":"group","in":"query","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"A page of events.","content":{"application/json":{"schema":{"type":"object","required":["events","next_cursor","has_more"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":"string","description":"The cursor for the next request"},"has_more":{"type":"boolean"}}}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The query is not valid (invalid_request, invalid_uid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks":{"get":{"operationId":"listWebhooks","summary":"List webhook endpoints","responses":{"200":{"description":"The endpoints.","content":{"application/json":{"schema":{"type":"object","required":["webhooks"],"properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWebhook","summary":"Add a webhook endpoint (at most 5); the secret is returned only here","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2000,"description":"https on a public address"},"kinds":{"type":"array","minItems":1,"items":{"type":"string","enum":["bankruptcy","composition","debt_enforcement","liquidation","deletion","deficiency","change","new_entry"]},"description":"Default: all kinds"}}}}}},"responses":{"201":{"description":"The endpoint with its signing secret.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string"}}}]}}}},"400":{"description":"The body is not JSON (invalid_json).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Already 5 endpoints (too_many_webhooks).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The URL is not allowed (invalid_url) or the body is not valid (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{id}":{"delete":{"operationId":"deleteWebhook","summary":"Delete a webhook endpoint","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such webhook (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{id}/test":{"post":{"operationId":"testWebhook","summary":"Send a sample event marked \"test\": true to the endpoint now (10 per minute)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"How the endpoint answered.","content":{"application/json":{"schema":{"type":"object","required":["delivered","status","error"],"properties":{"delivered":{"type":"boolean"},"status":{"type":["integer","null"],"description":"The HTTP status of the answer"},"error":{"type":["string","null"]}}}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such webhook (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/billing/checkout":{"post":{"operationId":"createCheckout","summary":"A Stripe Checkout link for the subscription; a person opens and pays it","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"blocks":{"type":"integer","minimum":1,"maximum":10,"default":1,"description":"Packages to start with; adjustable in Checkout"}}}}}},"responses":{"200":{"description":"The Checkout URL.","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"400":{"description":"The body is not JSON (invalid_json).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The account has a subscription; use the portal (already_subscribed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"blocks is not valid (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Billing is not configured or not set up (billing_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/billing/portal":{"post":{"operationId":"createPortalSession","summary":"A Stripe customer portal link: packages, payment method, invoices, cancellation","responses":{"200":{"description":"The portal URL.","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"401":{"description":"No valid API key (unauthorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests (rate_limited); see the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Billing is not configured or not set up (billing_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"event":{"post":{"operationId":"receiveEvent","summary":"A new event, posted to each endpoint whose kinds include it","parameters":[{"name":"UIDWatch-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.body\" with the endpoint secret>"},{"name":"UIDWatch-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"The same for every attempt of one event"},{"name":"UIDWatch-Delivery-Id","in":"header","required":true,"schema":{"type":"string"},"description":"One delivery to one endpoint"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Delivered. Anything else is retried after 1 min, 5 min, 30 min, 2 h, 6 h and 12 h."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key starting with uw_"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"description":"More about the problem, e.g. every invalid UID"}}}}},"Account":{"type":"object","required":["id","email","email_verified","plan","monitoring","limit","usage","trial_ends_at","last_scan_at","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"plan":{"type":"string","enum":["trial","monitor","paused"],"description":"monitor: a subscription; paused: trial or subscription ended"},"monitoring":{"type":"boolean","description":"Whether the list is compared with the gazette"},"limit":{"type":"integer","description":"Entries the plan monitors"},"usage":{"type":"integer","description":"Entries on the list"},"trial_ends_at":{"type":"string","format":"date-time"},"last_scan_at":{"type":["string","null"],"format":"date-time","description":"Last successful check of the gazette; null for a few minutes after a restart"},"created_at":{"type":"string","format":"date-time"}}},"WatchEntry":{"type":"object","required":["uid","group","reference","created_at","checked_at","monitored"],"properties":{"uid":{"type":"string"},"group":{"type":"string"},"reference":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"checked_at":{"type":["string","null"],"format":"date-time","description":"When the initial check was done; null while it is pending"},"monitored":{"type":"boolean","description":"False for entries beyond the plan limit"}}},"WatchInput":{"type":"object","required":["items"],"properties":{"items":{"type":"array","maxItems":25000,"items":{"type":"object","required":["uid"],"properties":{"uid":{"type":"string","maxLength":40,"example":"CHE-110.090.028 MWST"},"group":{"type":"string","maxLength":100},"reference":{"type":"string","maxLength":200}}}}}},"ChangeSummary":{"type":"object","required":["added","updated","unchanged"],"properties":{"added":{"type":"integer"},"updated":{"type":"integer","description":"Entries whose reference changed"},"unchanged":{"type":"integer"},"removed":{"type":"integer","description":"PUT only"}}},"Event":{"type":"object","required":["id","cursor","kind","historical","uid","group","reference","company_name","changes","publication","detected_at","test"],"properties":{"id":{"type":"string","format":"uuid"},"cursor":{"type":"string","description":"Its place in the stream, for ?cursor="},"kind":{"type":"string","enum":["bankruptcy","composition","debt_enforcement","liquidation","deletion","deficiency","change","new_entry"]},"historical":{"type":"boolean","description":"Published before the entry was added; never posted to webhooks"},"uid":{"type":"string"},"group":{"type":"string"},"reference":{"type":"string"},"company_name":{"type":"string"},"changes":{"type":"array","items":{"type":"string"},"description":"Change fields of a register change (HR02)"},"publication":{"type":"object","required":["id","number","date","rubric","sub_rubric","title","text","url","pdf_url"],"properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"string"},"date":{"type":"string","format":"date"},"rubric":{"type":"string"},"sub_rubric":{"type":"string"},"title":{"type":"object","required":["en","de","fr","it"],"properties":{"en":{"type":"string"},"de":{"type":"string"},"fr":{"type":"string"},"it":{"type":"string"}}},"text":{"type":["string","null"],"description":"Register text of HR publications"},"url":{"type":"string","description":"The notice in the gazette"},"pdf_url":{"type":"string","description":"Its signed PDF, the binding version"}}},"detected_at":{"type":"string","format":"date-time"},"test":{"type":"boolean"}}},"Webhook":{"type":"object","required":["id","url","kinds","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"kinds":{"type":"array","items":{"type":"string","enum":["bankruptcy","composition","debt_enforcement","liquidation","deletion","deficiency","change","new_entry"]}},"created_at":{"type":"string","format":"date-time"}}}}}}