Endpoint
GET https://api.testly.com/functions/v1/get-variant
Descrição
Retorna a variante que deve ser mostrada para um usuário específico.
A atribuição é determinística e o mesmo user_id sempre receberá a mesma variante para o mesmo experimento.
Características
✅ Determinístico : Mesmo usuário = mesma variante
✅ Baseado em hash : Usa user_id + experiment_key para calcular
✅ Respeita traffic allocation : Distribui usuários conforme pesos configurados
✅ Retorna null : Se experimento não estiver rodando
Autenticação
Envie sua API Key de uma das formas:
curl https://api.testly.com/functions/v1/get-variant \
-H "x-testly-auth: YOUR_API_KEY" \
-G \
--data-urlencode "experiment_key=homepage-hero-test" \
--data-urlencode "user_id=user_123"
Opção 2: Query Parameter
curl "https://api.testly.com/functions/v1/get-variant?experiment_key=homepage-hero-test&user_id=user_123&apikey=YOUR_API_KEY"
Segurança : Sempre use o header x-testly-auth em produção. Query parameters podem aparecer em logs.
Parâmetros
Query Parameters
Parâmetro Tipo Obrigatório Descrição experiment_keystring✅ Sim Identificador único do experimento user_idstring✅ Sim Identificador único do usuário (anônimo ou autenticado)
Header Tipo Obrigatório Descrição x-testly-authstring✅ Sim* Sua API Key (* ou via query param apikey)
Resposta
Sucesso (200 OK)
{
"variant_key" : "variant-b" ,
"variant_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"experiment_id" : "123e4567-e89b-12d3-a456-426614174000"
}
Campo Tipo Descrição variant_keystringChave da variante atribuída (ex: control, variant-b) variant_idstringUUID da variante experiment_idstringUUID do experimento
Experimento Não Rodando (200 OK)
{
"variant_key" : null ,
"reason" : "experiment_not_running"
}
Quando acontece:
Experimento está pausado ou inativo
Experimento não existe
Experimento foi deletado
Quando variant_key for null, implemente um fallback para mostrar a versão padrão do seu componente.
Sem Variantes Configuradas (200 OK)
{
"variant_key" : null ,
"reason" : "no_variants"
}
Erro: Parâmetros Faltando (400 Bad Request)
{
"error" : "Missing params or auth" ,
"details" : {
"experimentKey" : false ,
"userId" : true ,
"apiKey" : true
}
}
Erro: API Key Inválida (401 Unauthorized)
{
"error" : "Invalid API Key"
}
Exemplos
JavaScript / Fetch
async function getVariant ( experimentKey , userId ) {
const response = await fetch (
`https://api.testly.com/functions/v1/get-variant?experiment_key= ${ experimentKey } &user_id= ${ userId } ` ,
{
headers: {
'x-testly-auth' : 'YOUR_API_KEY'
}
}
);
if ( ! response . ok ) {
throw new Error ( `HTTP ${ response . status } : ${ await response . text () } ` );
}
return response . json ();
}
// Uso
const result = await getVariant ( 'homepage-hero-test' , 'user_123' );
console . log ( 'Variante:' , result . variant_key );
Python
import requests
def get_variant ( experiment_key , user_id , api_key ):
response = requests.get(
'https://api.testly.com/functions/v1/get-variant' ,
params = {
'experiment_key' : experiment_key,
'user_id' : user_id
},
headers = {
'x-testly-auth' : api_key
}
)
response.raise_for_status()
return response.json()
# Uso
result = get_variant( 'homepage-hero-test' , 'user_123' , 'YOUR_API_KEY' )
print ( f "Variante: { result[ 'variant_key' ] } " )
PHP
<? php
function getVariant ( $experimentKey , $userId , $apiKey ) {
$url = 'https://api.testly.com/functions/v1/get-variant?' . http_build_query ([
'experiment_key' => $experimentKey ,
'user_id' => $userId
]);
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
"x-testly-auth: $apiKey "
]);
$response = curl_exec ( $ch );
$statusCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
if ( $statusCode !== 200 ) {
throw new Exception ( "HTTP $statusCode : $response " );
}
return json_decode ( $response , true );
}
// Uso
$result = getVariant ( 'homepage-hero-test' , 'user_123' , 'YOUR_API_KEY' );
echo "Variante: " . $result [ 'variant_key' ];
?>
cURL
# Com header (recomendado)
curl -H "x-testly-auth: YOUR_API_KEY" \
"https://api.testly.com/functions/v1/get-variant?experiment_key=homepage-hero-test&user_id=user_123"
# Com query param
curl "https://api.testly.com/functions/v1/get-variant?experiment_key=homepage-hero-test&user_id=user_123&apikey=YOUR_API_KEY"
Como Funciona
1. Validação
O endpoint valida:
✅ API Key existe e pertence a uma organização ativa
✅ Experimento existe e pertence à organização
✅ Experimento está com status running
✅ Experimento tem variantes configuradas
2. Atribuição Determinística
hash = soma dos char codes de (user_id + experiment_key)
total_weight = soma de todos os traffic_weights das variantes
bucket = hash % total_weight
Exemplo:
user_id = "user_123"
experiment_key = "homepage-hero"
hash = 1234 (calculado)
total_weight = 100 (50 + 50)
bucket = 1234 % 100 = 34
Se bucket < 50 → Variante A
Se bucket >= 50 → Variante B
Resultado : O mesmo usuário sempre cai no mesmo bucket.
3. Cache Recomendado
Como a atribuição é determinística, você pode (e deve) cachear o resultado:
// Cache em memória
const variantCache = new Map ();
async function getVariantCached ( experimentKey , userId ) {
const cacheKey = ` ${ experimentKey } : ${ userId } ` ;
if ( variantCache . has ( cacheKey )) {
return variantCache . get ( cacheKey );
}
const result = await getVariant ( experimentKey , userId );
variantCache . set ( cacheKey , result );
return result ;
}
Casos de Uso
Server-Side Rendering (SSR)
// Next.js App Router
export async function generateMetadata ({ params }) {
const userId = cookies (). get ( 'user_id' )?. value || 'anonymous' ;
const { variant_key } = await getVariant ( 'homepage-hero' , userId );
return {
title: variant_key === 'variant-b'
? 'Experimente Agora - Testly'
: 'Comece Grátis - Testly'
};
}
API Gateway / Middleware
// Express.js middleware
app . use ( async ( req , res , next ) => {
const userId = req . cookies . user_id || 'anonymous' ;
try {
const { variant_key } = await getVariant ( 'pricing-test' , userId );
req . testlyVariant = variant_key ;
} catch ( error ) {
console . error ( 'Testly error:' , error );
req . testlyVariant = null ; // Fallback
}
next ();
});
app . get ( '/pricing' , ( req , res ) => {
if ( req . testlyVariant === 'variant-b' ) {
res . render ( 'pricing-3-col' );
} else {
res . render ( 'pricing-2-col' );
}
});
Edge Functions (Vercel/Cloudflare)
// Vercel Edge Function
export const config = { runtime: 'edge' };
export default async function handler ( req ) {
const userId = req . cookies . get ( 'user_id' ) || 'anonymous' ;
const { variant_key } = await getVariant ( 'homepage-hero' , userId );
return new Response ( JSON . stringify ({ variant: variant_key }), {
headers: { 'Content-Type' : 'application/json' }
});
}
Erros Comuns
Erro: “Invalid API Key”
Causa: API Key não existe ou está incorreta
Solução:
Verifique a key no dashboard
Certifique-se que está usando a key da organização correta
Verifique se não tem espaços extras na key
Erro: “experiment_not_running”
Causa: Experimento não está ativo
Solução:
Acesse o dashboard
Verifique se o experimento está com status “Running”
Se estiver pausado, ative-o
Erro: “no_variants”
Causa: Experimento não tem variantes configuradas
Solução:
Acesse o experimento no dashboard
Crie pelo menos 2 variantes (controle + teste)
Configure os pesos de tráfego
Timeout / Sem resposta
Causa: Rede lenta ou API temporariamente indisponível
Solução:
async function getVariantWithTimeout ( experimentKey , userId , timeout = 3000 ) {
const controller = new AbortController ();
const timeoutId = setTimeout (() => controller . abort (), timeout );
try {
const response = await fetch ( url , {
signal: controller . signal ,
headers: { 'x-testly-auth' : apiKey }
});
return await response . json ();
} catch ( error ) {
console . error ( 'Timeout ou erro:' , error );
return { variant_key: null }; // Fallback
} finally {
clearTimeout ( timeoutId );
}
}
Rate Limits
Plano Limite Free 100 req/min Pro 1.000 req/min Enterprise Customizável
Headers de resposta:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
Se exceder:
{
"error" : "Rate limit exceeded" ,
"retry_after" : 60
}
Próximos Passos
Track Event Registre impressões e conversões
Authentication Detalhes sobre API Keys
SDK React Use o SDK oficial (recomendado)
Exemplos Veja implementações completas