ES ▾
https://api.unrestrictedaiapi.com/v1uncensored2026-10-06
Obtener clave de API

Inicio rápido de Unrestricted AI API: Python, JavaScript, Go, PHP y Ruby

No necesitas un SDK para usar Unrestricted AI API. Habla HTTP estándar y JSON, por lo que cualquier lenguaje con un cliente HTTP funciona. Esta página te da una petición probada para Python, JavaScript, Go, PHP y Ruby, más los códigos de estado a manejar y la regla de reintento para evitar fallos en tus scripts.

Actualizado

Puntos clave

  1. Un endpoint, un id de modelo (sin censura), un token bearer: el mismo cuerpo de petición funciona en todos los lenguajes.
  2. Establece tiempos de espera explícitos. Las generaciones largas superan la mayoría de los tiempos de espera predeterminados del cliente.
  3. Comprueba el código de estado antes de analizar; los cuerpos de 402 y 403 son JSON válido sin un array de choices.
  4. Reintenta solo 429 y 503, con un backoff exponencial breve.

Toda la API en un curl

Olvídate del SDK por un momento. Todos los ejemplos siguientes envían lo mismo: un cuerpo JSON a POST /v1/chat/completions con un token bearer. Si puedes enviar eso, has terminado. Obtén una clave en la página de registro (el crédito de prueba no requiere detalles de pago), expórtala como API_KEY y ejecuta esto primero.

curl https://api.unrestrictedaiapi.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "messages": [{"role": "user", "content": "Write a two-line noir opening set in a laundromat."}],
    "max_tokens": 120
  }'

La respuesta es un objeto estilo OpenAI. El texto está en choices[0].message.content, y un bloque usage te dice cuánto costó la llamada en tokens. Hay un único modelo, uncensored, por lo que el campo model nunca cambia. Puedes confirmarlo con GET /v1/models.

curl https://api.unrestrictedaiapi.com/v1/models -H "Authorization: Bearer $API_KEY"

Dos límites que vale la pena memorizar antes de escribir código: la ventana de contexto es de 100.000 tokens compartidos entre prompt y completación, y max_tokens por defecto es 2048 a menos que lo aumentes (hasta 32.000). Si tu salida se detiene a mitad de oración, ese valor por defecto suele ser el culpable.

Python con httpx

httpx te da un cliente síncrono con tiempos de espera razonables y un gemelo asíncrono cuando lo necesites. Establece el tiempo de espera explícitamente. Las generaciones largas pueden tardar un poco y el valor predeterminado de cinco segundos las cortará.

import os
import httpx

resp = httpx.post(
    "https://api.unrestrictedaiapi.com/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={
        "model": "uncensored",
        "messages": [
            {"role": "system", "content": "You are a blunt, vivid fiction writer."},
            {"role": "user", "content": "Pitch a heist where the vault is a night market."},
        ],
        "temperature": 0.9,
        "max_tokens": 300,
    },
    timeout=60.0,
)
resp.raise_for_status()
print(resp.json()["choices"][0]["message"]["content"])

raise_for_status() convierte cualquier 4xx o 5xx en una excepción, lo cual está bien para un script. Para cualquier cosa de ejecución prolongada, envuelve la llamada para que dos estados tengan otra oportunidad: 429 (alcanzaste el límite por clave de 300 peticiones por minuto) y 503 (upstream_busy, que se resuelve en unos segundos). Todo lo demás, incluyendo 401, 402 y 403, no se arreglará con un reintento.

import os
import time
import httpx

def chat(messages, retries=3):
    for attempt in range(retries + 1):
        r = httpx.post(
            "https://api.unrestrictedaiapi.com/v1/chat/completions",
            headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
            json={"model": "uncensored", "messages": messages, "max_tokens": 400},
            timeout=60.0,
        )
        if r.status_code in (429, 503) and attempt < retries:
            time.sleep(2 ** attempt)
            continue
        r.raise_for_status()
        return r.json()["choices"][0]["message"]["content"]

print(chat([{"role": "user", "content": "Name five cursed objects found in a thrift store."}]))

Cambia httpx.post por httpx.AsyncClient().post dentro de un async def y tendrás la versión asíncrona con la misma carga útil.

JavaScript con fetch

Node 18 y versiones posteriores incluyen fetch, así que no hay nada que instalar. Guarda el archivo como .mjs (o establece "type": "module") para que el await de nivel superior funcione. Los navegadores tienen la misma API, pero no coloques la clave en el código del frontend. Proxy la llamada a través de tu propio backend.

const res = await fetch("https://api.unrestrictedaiapi.com/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "uncensored",
    messages: [{ role: "user", content: "Describe a villain's morning routine in four bullets." }],
    max_tokens: 250,
  }),
});

if (!res.ok) {
  const err = await res.json().catch(() => ({}));
  throw new Error(`HTTP ${res.status}: ${err?.error?.message ?? "unknown error"}`);
}

const data = await res.json();
console.log(data.choices[0].message.content);

Nota el orden de las comprobaciones. fetch solo rechaza por fallo de red, por lo que un 402 o 403 llega como una respuesta normal. Prueba res.ok tú mismo y lee el JSON de error, que siempre tiene la forma {"error":{"code":...,"message":...}}.

Go con net/http

Go necesita unas cuantas líneas más pero sin dependencias. Define solo los campos de la estructura que lees; encoding/json ignora el resto. Leer el cuerpo en bytes antes de verificar el estado te permite imprimir el mensaje de error del servidor cuando algo sale mal.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

type reply struct {
	Choices []struct {
		Message struct {
			Content string `json:"content"`
		} `json:"message"`
	} `json:"choices"`
}

func main() {
	payload, _ := json.Marshal(map[string]any{
		"model": "uncensored",
		"messages": []map[string]string{
			{"role": "user", "content": "Give me a ghost story in exactly three sentences."},
		},
		"max_tokens": 200,
	})

	req, _ := http.NewRequest("POST", "https://api.unrestrictedaiapi.com/v1/chat/completions", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		panic(fmt.Sprintf("HTTP %d: %s", resp.StatusCode, body))
	}

	var out reply
	if err := json.Unmarshal(body, &out); err != nil {
		panic(err)
	}
	fmt.Println(out.Choices[0].Message.Content)
}

Para producción, crea un http.Client{Timeout: 60 * time.Second} y reutilízalo. El cliente predeterminado no tiene ningún tiempo de espera, lo que hace que una petición atascada se convierta en una goroutine atascada.

PHP con cURL y Ruby con Net::HTTP

La extensión cURL de PHP ya está en la mayoría de los hosts. Construye el cuerpo con json_encode, devuelve la transferencia como una cadena y luego lee el estado con curl_getinfo. Saltarse la comprobación de estado es el error clásico: un cuerpo 402 se decodifica bien como JSON y tu código falla luego por una clave choices faltante.

<?php
$payload = json_encode([
    "model" => "uncensored",
    "messages" => [
        ["role" => "user", "content" => "Write a villanelle opening about a broken vending machine."],
    ],
    "max_tokens" => 200,
]);

$ch = curl_init("https://api.unrestrictedaiapi.com/v1/chat/completions");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 60,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($body === false || $status !== 200) {
    fwrite(STDERR, "HTTP $status: $body\n");
    exit(1);
}

$data = json_decode($body, true);
echo $data["choices"][0]["message"]["content"], "\n";

En un host compartido con un max_execution_time bajo, mantén max_tokens modesto o mueve la llamada a un worker de cola.

La biblioteca estándar es suficiente aquí también. ENV.fetch genera un error inmediatamente si falta la variable, lo cual es mejor que enviar un token bearer vacío y depurar un 401 durante diez minutos.

require "net/http"
require "json"
require "uri"

uri = URI("https://api.unrestrictedaiapi.com/v1/chat/completions")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('API_KEY')}"
req["Content-Type"] = "application/json"
req.body = JSON.generate(
  model: "uncensored",
  messages: [{ role: "user", content: "Invent a tavern rumor that sounds too specific to be fake." }],
  max_tokens: 200
)

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 60) { |http| http.request(req) }
abort("HTTP #{res.code}: #{res.body}") unless res.is_a?(Net::HTTPSuccess)

puts JSON.parse(res.body).dig("choices", 0, "message", "content")

Si luego pasas a Rails, el mismo cuerpo funciona desde un trabajo en segundo plano. Mantén la llamada fuera del ciclo de petición; las generaciones son más lentas que una consulta a base de datos.

Ambos fragmentos envían exactamente el cuerpo que envía el de Python, que es el punto: si un lenguaje funciona y otro no, compara el JSON, no el cliente. Imprime el cuerpo de la petición raw una vez y compáralo byte a byte. Nueve de cada diez veces, el culpable es un encabezado Content-Type faltante o un nombre de modelo escrito con mayúscula.

Streaming sin librería

El streaming es el único lugar donde HTTP estándar te pide un poco más. Con stream: true el servidor responde con eventos enviados por el servidor: cada línea comienza con data: , lleva un fragmento JSON y el stream termina con data: [DONE]. Se añade automáticamente un fragmento de uso final, por lo que obtienes recuentos de tokens incluso al hacer streaming. Ese fragmento no tiene entradas choices, por eso el bucle a continuación verifica antes de indexar.

import json
import os
import httpx

body = {
    "model": "uncensored",
    "messages": [{"role": "user", "content": "Tell a campfire story about a lighthouse keeper."}],
    "stream": True,
    "max_tokens": 400,
}
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

with httpx.stream("POST", "https://api.unrestrictedaiapi.com/v1/chat/completions",
                  headers=headers, json=body, timeout=60.0) as r:
    r.raise_for_status()
    for line in r.iter_lines():
        if not line.startswith("data: "):
            continue
        data = line[6:]
        if data == "[DONE]":
            break
        chunk = json.loads(data)
        if chunk.get("choices"):
            print(chunk["choices"][0]["delta"].get("content") or "", end="", flush=True)
print()

El mismo patrón se adapta directamente. En JavaScript, lee res.body con un lector y divide por líneas nuevas. En Go, envuelve resp.Body en un bufio.Scanner. En Ruby, pasa un bloque a http.request y usa read_body. En PHP, establece un callback CURLOPT_WRITEFUNCTION. La lógica nunca cambia: elimina el prefijo, detente en el sentinel, analiza el JSON, imprime el delta.

Prueba de humo de cinco minutos y verificación de presupuesto

Antes de construir sobre cualquiera de estos fragmentos, ejecuta una verificación rápida. Primero, llama a /v1/models con tu clave; un 200 prueba la clave y la ruta de red. Segundo, envía la petición de chat más pequeña posible con max_tokens establecido en 20. Tercero, rompe algo a propósito, como un token bearer vacío, y confirma que tu código muestra el 401 claramente en lugar de fallar por un campo faltante.

Luego haz la aritmética una vez para que nada te sorprenda. Los precios son $0,25 por millón de tokens de entrada y $1,00 por millón de tokens de salida. Como suposición ilustrativa, digamos que una petición envía 600 tokens de prompt y recibe 400 tokens. Eso es 600 x $0,25 / 1 000 000 = $0,00015 de entrada, más 400 x $1,00 / 1 000 000 = $0,0004 de salida, unos $0,00055 por llamada. El crédito de prueba de $0,50 cubriría aproximadamente 900 llamadas de ese tamaño. Tus prompts reales serán diferentes, así que lee el bloque usage en algunas respuestas y multiplica a partir de ahí.

El crédito de prueba dura siete días y no requiere detalles de pago, lo que lo hace suficiente para probar los cinco idiomas. Si quieres un caso de uso al que apuntar, la guía de contenido NSFW muestra un ejemplo completo. Recuerda que una clave pertenece a una cuenta; si la regeneras, actualiza todos los scripts a la vez, porque la clave antigua deja de funcionar inmediatamente.

Errores que se ven iguales en todos los idiomas

Como la API es HTTP estándar, el manejo de errores es idéntico sin importar el lenguaje que elijas. Memoriza esta tabla y podrás portar cualquier fragmento anterior.

EstadoSignificadoAcción
400Petición incorrecta, como prompt más max_tokens superior a 100kReduce el prompt o baja max_tokens
401Clave faltante o inválidaVerifica API_KEY; una clave regenerada invalida la anterior al instante
402no_credit: saldo agotado o crédito de prueba expiradoRecarga el saldo prepago
403content_blockedNo reintentes; el contenido sexual que involucra a menores siempre se bloquea
429Más de 300 peticiones por minutoEspera y reintenta
503upstream_busyReintenta en unos segundos

Una vez que lo básico funcione, configura stream: true para obtener salida token por token y lee los eventos enviados por el servidor línea por línea. Mejora tus prompts con la guía de prompting, o integra la misma llamada en una plataforma de chat usando la guía para bots. Los precios están en la página de precios.

Preguntas y respuestas

¿Necesito el SDK de OpenAI para llamar a esta API?

No. Los ejemplos aquí usan solo las herramientas HTTP estándar de cada lenguaje. Los SDKs de OpenAI también funcionan si apuntas su URL base a https://api.unrestrictedaiapi.com/v1.

¿Qué ID de modelo debo enviar?

Siempre "sin censura". Hay un único modelo, y GET /v1/models lo lista.

¿Por qué mi respuesta se detuvo a mitad de una oración?

El max_tokens por defecto es 2048. Auméntalo por petición, hasta 32.000, siempre que el prompt más la respuesta se mantengan dentro de la ventana de 100.000 tokens.

¿Qué errores debería reintentar mi código?

Reintenta 429 (límite de peticiones) y 503 (upstream_busy) tras un breve retraso. 400, 401, 402 y 403 requieren un cambio en tu lado, por lo que reintentarlos desperdicia llamadas.

Tu clave está a un formulario de distancia

Crea una cuenta, copia la clave, cambia la URL base. Eso es toda la configuración.

Obtener clave de API