Skip to content

Device keys

Media uploads (profile photos and chat media) are protected by a per-session device key. Register a P-256 key with the endpoints below, then sign each upload as described in Security headers -> Device-key upload signing.

Fetch device-key challenge

Requires Authorization.

First step of device-key registration. Returns a one-time challenge to fold into the registration signature. See Security headers -> Device-key upload signing.

POST /v1/verification/device-keys/challenge

Response:

  • challenge — Opaque challenge string to fold into the registration signature.
  • expiresAt — ISO-8601 instant after which the challenge is no longer accepted.

Register device key

Requires Authorization.

Registers the session's P-256 public key after signing the challenge from Fetch device-key challenge. The returned keyId is then used to sign media uploads.

POST /v1/verification/device-keys

Body:

  • publicKey — base64url (no padding) of the device key SubjectPublicKeyInfo DER.
  • keyId — base64url (no padding) of SHA-256(publicKey DER).
  • registrationSignature — base64url (no padding) DER ECDSA-P256-SHA256 signature over userId|keyId|publicKey|androidId|challenge.

Response:

  • keyId — string, The accepted keyId, echoed back.

Register device key (reCAPTCHA)

Requires Authorization.

Like Register device key but with a reCAPTCHA Enterprise token in the X-Grindr-Captcha-Token header, chosen over v1 endpoint when the recaptcha_device_key_registration server flag is on.

POST /v2/verification/device-keys

Headers:

  • X-Grindr-Captcha-Token — string, reCAPTCHA Enterprise token, action device_key_registration.

Body:

  • publicKey — base64url (no padding) of the device key SubjectPublicKeyInfo DER.
  • keyId — base64url (no padding) of SHA-256(publicKey DER).
  • registrationSignature — base64url (no padding) DER ECDSA-P256-SHA256 signature over userId|keyId|publicKey|androidId|challenge.

Response:

  • keyId — string, The accepted keyId, echoed back.

ChallengeResponse

  • challenge — Opaque challenge string to fold into the registration signature.
  • expiresAt — ISO-8601 instant after which the challenge is no longer accepted.

RegisterKeyRequest

  • publicKey — base64url (no padding) of the device key SubjectPublicKeyInfo DER.
  • keyId — base64url (no padding) of SHA-256(publicKey DER).
  • registrationSignature — base64url (no padding) DER ECDSA-P256-SHA256 signature over userId|keyId|publicKey|androidId|challenge.

RegisterKeyResponse

  • keyId — string, The accepted keyId, echoed back.

UploadSigningErrorResponse

Problem body returned when device-key signature verification fails.

  • type — string, Failure kind; contains timestamp_drift or nonce_replayed. or null, optional
  • detail — For timestamp_drift, the server's current time as an ISO-8601 instant; resync the clock offset and retry. or null, optional

Open Grind is not affiliated with Grindr in any way.