Drawer, WIP
NOTE
This page is a work in progress. Endpoints below haven't been fully researched.
Get media in drawer
Requires Authorization.
GET /v4/chat/media/drawerResponse:
Array of DrawerMedia.
Get media in drawer for a conversation
Requires Authorization.
GET /v4/chat/media/drawer/{conversationId}Response:
Array of DrawerMedia.
Add media to drawer
Requires Authorization.
Takes a mediaId from uploading. Videos are accepted and listed as video/mp4.
PUT /v4/chat/media/drawer/{mediaId}Response:
Empty.
Errors:
500— Repeated requests cause 500 HTTP status "Internal Error".
Delete media from drawer
Requires Authorization.
Removes the item from the drawer. Album copies made with Add drawer media to an album are separate files and stay. The CDN may keep serving the deleted file's signed url from cache.
Repeated requests are completed without errors.
DELETE /v4/chat/media/drawer/{mediaId}Response:
Empty with HTTP status 202.
Upload media
Requires Authorization.
Requires a correct Content-Type. Set length for audio and video, and looping for video. Videos are uploaded as video/mp4.
Images are stored as a single frame: an animated GIF becomes a JPEG of its first frame, and its mediaHash is the SHA-256 of that JPEG. A video is stored as uploaded, and its mediaHash is the SHA-256 of the uploaded bytes.
POST /v5/chat/media/uploadQuery:
length— long integer, Duration in milliseconds., optionallooping— boolean, optionaltakenOnGrindr— boolean, Media captured with the in-app camera.
Body:
Binary file.
Response:
mediaId— long integerurl— URLmediaHash— string, See Media -> Public CDN files -> Profile Images
Errors:
400—{"type":"urn:gr:err:bad_request","title":"Invalid request","status":400,"traceId":"…","detail":"Image parsing failed for WEBP. …"}when an image cannot be decoded, e.g. an animated WebP.
Upload media (signed)
Requires Authorization.
Signed version of the unsigned Upload media. A correct Content-Type request header is required, and the request must carry a valid device-key signature over the raw request body; see Security headers -> Device-key upload signing. length and looping are never sent here. All media uploaded through this endpoint are marked as "Taken on Grindr" server-side.
POST /v6/chat/media/uploadQuery (optional):
length— long integer, optionallooping— boolean, optional
Headers:
X-Key-Id— base64url (no padding)SHA-256of the device key SPKI — thekeyIdfrom Register device key.X-Sig— base64url (no padding) DER ECDSA-P256-SHA256 signature over the UTF-8 stringbodyHash|timestamp|userId|androidId|nonce. See Security headers -> Device-key upload signing.X-Timestamp— Signing time as Unix epoch milliseconds (decimal string); must equal thetimestampinside the signed string.X-Nonce— base64url (no padding) of 32 random bytes, unique per request; must equal thenonceinside the signed string.
Body:
Binary file.
Response:
mediaId— long integerurl— URLmediaHash— string, See Media -> Public CDN files -> Profile Images
Errors:
422— Media rejected by moderation.4xx— Signature rejected; seeUploadSigningErrorResponse(timestamp_drift/nonce_replayed).
DrawerMedia
id— long integerurl— URLcontentType— stringcreatedTs— unix timestamp in millisecondsused— booleantakenOnGrindr— boolean
MediaUploadResponse
mediaId— long integerurl— URLmediaHash— string, See Media -> Public CDN files -> Profile Images
MediaUploadProblemResponse
RFC-7807 problem body returned on a 422 when uploaded media is blocked by moderation.
type— string, error URN —urn:gr:err:banned_imageorurn:gr:err:banned_video, optionaltitle— string, optionalstatus— integer,422, optionaltraceId— string, optional