Skip to content

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/drawer

Response:

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/upload

Query:

  • length — long integer, Duration in milliseconds., optional
  • looping — boolean, optional
  • takenOnGrindr — boolean, Media captured with the in-app camera.

Body:

Binary file.

Response:

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/upload

Query (optional):

  • length — long integer, optional
  • looping — boolean, optional

Headers:

  • X-Key-Id — base64url (no padding) SHA-256 of the device key SPKI — the keyId from Register device key.
  • X-Sig — base64url (no padding) DER ECDSA-P256-SHA256 signature over the UTF-8 string bodyHash|timestamp|userId|androidId|nonce. See Security headers -> Device-key upload signing.
  • X-Timestamp — Signing time as Unix epoch milliseconds (decimal string); must equal the timestamp inside the signed string.
  • X-Nonce — base64url (no padding) of 32 random bytes, unique per request; must equal the nonce inside the signed string.

Body:

Binary file.

Response:

Errors:

  • 422 — Media rejected by moderation.
  • 4xx — Signature rejected; see UploadSigningErrorResponse (timestamp_drift / nonce_replayed).

DrawerMedia ​

  • id — long integer
  • url — URL
  • contentType — string
  • createdTs — unix timestamp in milliseconds
  • used — boolean
  • takenOnGrindr — boolean

MediaUploadResponse ​

MediaUploadProblemResponse ​

RFC-7807 problem body returned on a 422 when uploaded media is blocked by moderation.

  • type — string, error URN — urn:gr:err:banned_image or urn:gr:err:banned_video, optional
  • title — string, optional
  • status — integer, 422, optional
  • traceId — string, optional

Open Grind is not affiliated with Grindr in any way.