Última transacción
curl --request GET \
--url https://clientapi.retailgrid.io/v1/transactions/latestimport requests
url = "https://clientapi.retailgrid.io/v1/transactions/latest"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://clientapi.retailgrid.io/v1/transactions/latest', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://clientapi.retailgrid.io/v1/transactions/latest",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://clientapi.retailgrid.io/v1/transactions/latest"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://clientapi.retailgrid.io/v1/transactions/latest")
.asString();require 'uri'
require 'net/http'
url = URI("https://clientapi.retailgrid.io/v1/transactions/latest")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyTransacciones
Última transacción
Obtén la última transacción almacenada según su marca de tiempo de negocio, opcionalmente dentro de una sola tienda.
GET
/
v1
/
transactions
/
latest
Última transacción
curl --request GET \
--url https://clientapi.retailgrid.io/v1/transactions/latestimport requests
url = "https://clientapi.retailgrid.io/v1/transactions/latest"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://clientapi.retailgrid.io/v1/transactions/latest', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://clientapi.retailgrid.io/v1/transactions/latest",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://clientapi.retailgrid.io/v1/transactions/latest"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://clientapi.retailgrid.io/v1/transactions/latest")
.asString();require 'uri'
require 'net/http'
url = URI("https://clientapi.retailgrid.io/v1/transactions/latest")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyGET https://clientapi.retailgrid.io/v1/transactions/latest devuelve una transacción
con el mayor transaction_timestamp almacenado no nulo en todo el espacio de nombres de datos
de tu organización. No requiere paginación ni exportación. El orden de las listas existentes y los cursores no cambian.
Autentícate con la misma clave de API Bearer que en los demás endpoints públicos:
curl --fail-with-body \
'https://clientapi.retailgrid.io/v1/transactions/latest' \
-H "Authorization: Bearer $RETAILGRID_API_KEY"
store_id, el UUID canónico de una tienda de la organización:
curl --fail-with-body \
'https://clientapi.retailgrid.io/v1/transactions/latest?store_id=00000000-0000-0000-0000-00000000000b' \
-H "Authorization: Bearer $RETAILGRID_API_KEY"
{"item": null}
{
"item": {
"sku": null,
"region": null,
"sales_value": null,
"gross_profit": null,
"stock_after_sale": null,
"regular_price": null,
"promo_type": null,
"zone_price": null,
"external_transaction_id": null,
"unit_cost": null,
"discount_rate": null,
"currency": null,
"tax_rate": null,
"transaction_type": null,
"id": "00000000-0000-0000-0000-000000000003",
"item_id": "item-3",
"store_id": "00000000-0000-0000-0000-00000000000b",
"transaction_timestamp": "2026-01-01T22:30:00",
"quantity": "1.25",
"selling_price": "9.90"
}
}
Orden y zonas horarias
La selección ordena portransaction_timestamp DESC, id DESC, ignorando las fechas nulas.
Para fechas iguales, gana la cadena UUID canónica mayor. updated_at, el orden de llegada
y el actor que hace la solicitud no afectan la selección dentro del espacio de nombres.
BigQuery almacena este campo como DATETIME sin desplazamiento horario. Las entradas de la API con zona horaria se
normalizan a UTC antes de almacenarse: 2026-01-02T00:30:00+02:00 y
2026-01-01T22:30:00Z se convierten ambas en 2026-01-01T22:30:00. Las entradas sin zona horaria conservan el
valor de reloj indicado. Los valores históricos sin zona horaria no tienen una zona horaria original
recuperable; la respuesta no inventa un sufijo Z ni una fecha local del cliente.
Sincronización y costo
Este máximo no es un punto de control de sincronización sin pérdidas. Reanudar estrictamente después de él puede omitir llegadas tardías, registros con fecha retroactiva, correcciones y marcas de tiempo iguales. El desempate determinista por ID no resuelve esos casos. Concilia con las listas o exportaciones de transacciones compatibles; si usasupdated_since, solapa las ventanas de tiempo y
aplica los registros de forma idempotente por ID de transacción. Sigue los cursores devueltos con la misma
selección y el mismo límite. El endpoint de última transacción no tiene en sí un filtro por ventana de fechas.
La base de datos filtra, ordena y limita el resultado a una fila; la aplicación decodifica
solo esa fila. Cada llamada puede seguir recorriendo particiones históricas, y las llamadas repetidas
pueden incurrir cada una en costo de lectura de la fuente. LIMIT 1 no garantiza poda de particiones ni
bajo costo. Se aplican la contabilidad de uso y los topes de consulta existentes; no se crea ningún mecanismo alternativo
sin límite ni ninguna exportación completa retenida. Usa las exportaciones asíncronas
para extracciones grandes.
