{"openapi":"3.1.0","info":{"title":"Street Art Cities Profiles API","description":"Look up people's public profiles, and the artworks someone liked and saw.","version":"1.0.0"},"servers":[{"url":"https://streetartcities.com","description":"Production"},{"url":"https://streetartdev.com","description":"Development"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ProfileItem":{"type":"object","properties":{"type":{"type":"string","description":"What it is: `marker` for an artwork or other place on the map, or `comment` for a comment on one"},"id":{"type":"string"},"title":{"type":"string"},"artistsString":{"description":"The artists' names, separated by commas","type":"string"},"thumbnail":{"type":"string"},"href":{"description":"Link to it on Street Art Cities","type":"string"},"comment":{"description":"For comments: what the comment says","type":"string"},"createdAt":{"description":"When they liked, saw or hunted it. Seen dates can be in the past, when someone logged an old visit","type":"string"}},"required":["type","id"]}}},"security":[{"bearerAuth":[]}],"paths":{"/api/profiles/user/{userId}":{"get":{"operationId":"getApiProfilesUserByUserId","tags":["Profiles"],"x-scope-required":["profiles:read"],"summary":"Get a profile","description":"Someone's public profile: their name, picture, bio, links and badges.","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The profile","content":{"application/json":{"schema":{"type":"object","properties":{"@type":{"type":"string","const":"Profile"},"id":{"type":"string"},"href":{"type":"string","description":"Link to their profile on Street Art Cities"},"displayName":{"type":"string"},"avatar":{"description":"Link to their profile picture","type":"string"},"bio":{"type":"string"},"statusMessage":{"description":"A short status they've set, like where they're travelling","type":"object","properties":{"description":{"type":"string"},"endsAt":{"type":"string"}},"required":["description"],"additionalProperties":{}},"socialLinks":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"url":{"type":"string"}},"required":["type","url"]},"description":"Links to their website and social media"},"followerCount":{"type":"number"},"followingCount":{"type":"number"},"decorations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"image":{"type":"string"}},"required":["id","title","image"]},"description":"Roles shown next to their name, like Country Manager"},"badges":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"}},"required":["id","title","description","image"]},"description":"Badges they've earned"},"createdAt":{"description":"When they joined","type":"string"}},"required":["@type","id","href","displayName","bio","socialLinks","followerCount","followingCount","decorations","badges"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"401":{"description":"Not logged in","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"403":{"description":"The app doesn't have the profiles:read scope","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}}}}},"/api/profiles/me/likes":{"get":{"operationId":"getApiProfilesMeLikes","tags":["Profiles"],"x-scope-required":["likes:read"],"summary":"List your likes","description":"The artworks and comments the person liked, newest first. Things that were deleted since only have a `type` and `id`. Use `updatedSince` to only get what they liked since you last checked.","responses":{"200":{"description":"A page of likes","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ProfileItem"}},"page":{"type":"number"},"perPage":{"type":"number"},"total":{"type":"number","description":"How many there are, over all pages"}},"required":["items","page","perPage","total"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"401":{"description":"Not logged in","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"403":{"description":"The app doesn't have the likes:read scope","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"updatedSince","schema":{"type":"string","format":"date-time","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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"description":"Only what was added to the list since this time, like `2026-09-01T00:00:00Z`"},{"in":"query","name":"page","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991},"description":"Which page of results, starting at 1"},{"in":"query","name":"perPage","schema":{"default":20,"type":"integer","minimum":1,"maximum":100},"description":"How many results per page (20 by default, at most 100)"}]}},"/api/profiles/me/seen":{"get":{"operationId":"getApiProfilesMeSeen","tags":["Profiles"],"x-scope-required":["seen:read"],"summary":"List what you've seen","description":"The artworks the person marked as seen or hunted themselves, newest first. Artworks they saw more than once are only listed once, with the last time they saw them. Use `updatedSince` to only get what was added since you last checked, including old visits they logged since.","responses":{"200":{"description":"A page of seen artworks","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ProfileItem"}},"page":{"type":"number"},"perPage":{"type":"number"},"total":{"type":"number","description":"How many there are, over all pages"}},"required":["items","page","perPage","total"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"401":{"description":"Not logged in","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}},"403":{"description":"The app doesn't have the seen:read scope","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{}}},"required":["message"]}},"required":["error"]}}}}},"parameters":[{"in":"query","name":"updatedSince","schema":{"type":"string","format":"date-time","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])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"description":"Only what was added to the list since this time, like `2026-09-01T00:00:00Z`"},{"in":"query","name":"page","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991},"description":"Which page of results, starting at 1"},{"in":"query","name":"perPage","schema":{"default":20,"type":"integer","minimum":1,"maximum":100},"description":"How many results per page (20 by default, at most 100)"}]}}}}