{"data":{"name":"Tapter Profile API","version":"v1","baseUrl":"https://tapter.one/api/v1","authentication":{"scheme":"Bearer","header":"Authorization: Bearer <token>","tokenPrefix":"tptr_","issuedAt":"https://tapter.one/settings/api","abilities":{"profile:read":"Read profiles, slots and discovery.","profile:write":"Create, change and delete slots, update profiles, upload files."}},"discovery":{"me":"https://tapter.one/api/v1/me","slotTypes":"https://tapter.one/api/v1/slot-types","profileSettings":"https://tapter.one/api/v1/profiles/{profile}/settings","openapi":"https://tapter.one/api/v1/openapi.json","profileMarkdown":"https://tapter.one/api/v1/profiles/{profile}/markdown","musicLookup":"https://tapter.one/api/v1/music/lookup?query=<UPC|ISRC|release link|title>"},"conventions":{"envelope":"Success: {data, meta?}. Error: {message, code, errors?, documentation?}.","keys":"camelCase","dates":"ISO 8601","strictWrite":"Unknown or server-computed fields in data return 422 listing every offending key.","tolerantRead":"Legacy slots are returned with \"supported\": false and can be deleted or reordered, but not edited.","dryRun":"Send \"Precognition: true\" on any write request to validate without executing.","login":"A profile login is its public URL. It can be changed through PATCH /profiles/{profile}/settings, but the old address stops working immediately and is not redirected, so existing links, QR codes and NFC tags break. Change it only when the user explicitly asked to, and check availability with GET /profiles/check-login first.","idempotency":"Send \"Idempotency-Key: <string>\" on POST. Repeating it within 24h returns the stored response.","images":"Profile avatar is rendered as a circle: send a square (1:1, 800x800+). Profile bgImage is optional — do not generate one unless the user asked — and is rendered full width without cropping: send 16:9 landscape (1600x900+), otherwise it pushes the whole page below the fold. Uploads are downscaled to 800px width, so larger than ~1600px brings nothing. POST /files takes either a multipart \"file\" (up to 50 MB) or JSON {\"url\": \"https://…\"} and downloads it for you (http/https, up to 10 MB).","preview":"GET /profiles/{profile}/markdown renders the whole page as markdown. Read it back after writing to catch empty blocks and a wrong order before showing the link to the user."},"limits":{"requestsPerSecond":5,"requestsPerMinute":60,"slotsPerProfile":100,"profilesPerUser":100,"tokensPerUser":5},"examples":{"readProfile":"curl -H 'Authorization: Bearer $TAPTER_TOKEN' 'https://tapter.one/api/v1/profiles/coffeeshop?include=slots'","addButton":"curl -X POST -H 'Authorization: Bearer $TAPTER_TOKEN' -H 'Content-Type: application/json' -H 'Idempotency-Key: add-button-1' -d '{\"type\":\"button\",\"data\":{\"title\":\"Book now\",\"link\":\"https://example.com/book\",\"style\":\"primary\"}}' 'https://tapter.one/api/v1/profiles/coffeeshop/slots'","reorderSlots":"curl -X PUT -H 'Authorization: Bearer $TAPTER_TOKEN' -H 'Content-Type: application/json' -d '{\"order\":[12,7,33]}' 'https://tapter.one/api/v1/profiles/coffeeshop/slots/order'","addMusic":"curl -H 'Authorization: Bearer $TAPTER_TOKEN' 'https://tapter.one/api/v1/music/lookup?query=USRC11700001' # then POST data.slot as-is to https://tapter.one/api/v1/profiles/coffeeshop/slots","whoAmI":"curl -H 'Authorization: Bearer $TAPTER_TOKEN' 'https://tapter.one/api/v1/me'","previewPage":"curl -H 'Authorization: Bearer $TAPTER_TOKEN' 'https://tapter.one/api/v1/profiles/coffeeshop/markdown'","uploadByUrl":"curl -X POST -H 'Authorization: Bearer $TAPTER_TOKEN' -H 'Content-Type: application/json' -d '{\"url\":\"https://example.com/logo.png\"}' 'https://tapter.one/api/v1/files'","changeLanguage":"curl -X PATCH -H 'Authorization: Bearer $TAPTER_TOKEN' -H 'Content-Type: application/json' -d '{\"languageCode\":\"kk\"}' 'https://tapter.one/api/v1/profiles/coffeeshop/settings'"},"notAvailable":["Deleting a profile (link) — dashboard only, it is irreversible.","Profile themes — not open in the dashboard yet, so the API neither returns nor accepts them.","Events and storefront catalogs — event slots are read-only.","Batch replace of all slots — use POST/PATCH/DELETE per slot."]}}