Ir al contenido

Autenticación y firma

Cada petición lleva tres cabeceras:

Cabecera Valor
Authorization Bearer rvw_live_…: la llave. Dice quién llama.
X-Timestamp La hora actual en segundos Unix (1760630400).
X-Signature sha256= + el HMAC-SHA256 en hexadecimal, con el secreto de firma, de la cadena {X-Timestamp}.{body crudo}.
cadena = X-Timestamp + "." + body
firma = "sha256=" + hex( HMAC_SHA256( secreto, cadena ) )
  • El body es el texto exacto que mandas, byte por byte. Si firmas un JSON y luego lo vuelves a serializar con otro espacio, la firma no coincide.
  • En un GET o un POST sin body, el body es la cadena vacía: firmas 1760630400..
  • El timestamp va dentro de la firma y aceptamos hasta 5 minutos de diferencia con nuestro reloj. Así nadie puede reenviar una petición capturada.
Ventana de terminal
LLAVE="rvw_live_..."
SECRETO="rvwsig_..."
TS=$(date +%s)
BODY='{"order":{"shopify_order_id":"456"},"locale":"es"}'
FIRMA=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRETO" | sed 's/^.* //')
curl https://reviews.leadit.tech/api/v1/review-requests \
-H "Authorization: Bearer $LLAVE" \
-H "X-Timestamp: $TS" \
-H "X-Signature: sha256=$FIRMA" \
-H "Content-Type: application/json" \
-d "$BODY"

Cada llave tiene un alcance que eliges al crearla y no cambia después. Para cambiarlo, crea otra y revoca la vieja. Puedes tener hasta 5 llaves.

Alcance En la app Qué puede hacer
read Solo lectura Todos los GET.
moderate Solicitudes y moderación Lo anterior, más pedir, confirmar, enviar ahora y cancelar solicitudes; crear, moderar y responder reseñas; subir fotos y videos.
full Acceso total Todo: también borrar reseñas, cambiar ajustes, reintentar webhooks e importar en lote.

Una llamada fuera del alcance responde 403 insufficient_scope, con el alcance que haría falta en details.

POST /reviews y POST /reviews/import aceptan la cabecera Idempotency-Key (un UUID, por ejemplo). Si repites la misma petición con la misma llave dentro de 24 horas, te devolvemos la misma respuesta con la cabecera Idempotent-Replayed: true, sin crear nada otra vez.

  • La misma Idempotency-Key con otro body responde 422 idempotency_key_reused.
  • Mientras la primera sigue en curso, la segunda responde 409 idempotency_in_progress.
  • Un error 5xx no se guarda: puedes reintentar.

POST /review-requests no necesita la cabecera: si la orden ya tiene solicitud, devuelve la misma con 200.

120 peticiones por minuto por llave. Si te pasas, respondemos 429 rate_limited con Retry-After: 60.