GET
/health
Sin token
Comprueba que el servicio está en pie
Sonda de vida para el balanceador, el monitor o el despliegue. No consulta el almacén ni las fuentes externas, así que responde aunque la sincronización esté fallando. Es el único endpoint que se puede llamar en bucle sin miramientos.
Ejemplo
Ejemplo · cURLcurl -s https://api-security.ipsmart.app/health
Ejemplo · Node.jsconst r = await fetch('https://api-security.ipsmart.app/health');
console.log(r.status, await r.json());
Ejemplo · JavaScript (navegador)// El navegador puede llamar al servicio: CORS está abierto para lo público.
const r = await fetch('https://api-security.ipsmart.app/health');
console.log(r.status, await r.json());
Ejemplo · Pythonimport requests
r = requests.get("https://api-security.ipsmart.app/health", timeout=10)
print(r.status_code, r.json())
Ejemplo · PHP<?php
$json = file_get_contents('https://api-security.ipsmart.app/health');
var_dump(json_decode($json, true));
Ejemplo · Goresp, err := http.Get("https://api-security.ipsmart.app/health")
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
fmt.Println(resp.Status)
Ejemplo · JavaHttpClient c = HttpClient.newHttpClient();
HttpRequest r = HttpRequest.newBuilder(URI.create("https://api-security.ipsmart.app/health")).build();
System.out.println(c.send(r, BodyHandlers.ofString()).body());
Ejemplo · C#using var http = new HttpClient();
var body = await http.GetStringAsync("https://api-security.ipsmart.app/health");
Console.WriteLine(body);
Ejemplo · Rubyrequire "net/http"
puts Net::HTTP.get(URI("https://api-security.ipsmart.app/health"))
GET
/api/security/latest
Sin token
Boletín público de vulnerabilidades, sin token
El mismo recurso tiene dos caras. Sin cabecera de autorización devuelve, por cada vulnerabilidad, el problema y la recomendación de qué hacer con él, además del identificador, la severidad, la puntuación y los productos afectados. Lo que no sale es el detalle explotable ni los pasos de pentest: eso es lo que cuesta el token. Es lo que alimenta cualquier panel o web que quiera mostrar el estado del día y qué hacer al respecto.
Ejemplo
Ejemplo · cURLcurl -s https://api-security.ipsmart.app/api/security/latest
Ejemplo · Node.jsconst r = await fetch('https://api-security.ipsmart.app/api/security/latest');
const { total, data } = await r.json();
for (const v of data) console.log(v.severidad, v.cveId, v.titulo);
Ejemplo · JavaScript (navegador)const r = await fetch('https://api-security.ipsmart.app/api/security/latest');
const { data } = await r.json();
const lista = document.querySelector('#boletin');
for (const v of data) {
const li = document.createElement('li');
// textContent y no innerHTML: el titulo viene de fuera y no se pinta como marcado.
li.textContent = v.severidad + ' ' + v.cveId + ' ' + v.titulo;
lista.append(li);
}
Ejemplo · Pythonimport requests
r = requests.get("https://api-security.ipsmart.app/api/security/latest", timeout=15)
for v in r.json()["data"]:
print(v["severidad"], v["cveId"], v["titulo"])
Ejemplo · PHP<?php
$r = json_decode(file_get_contents('https://api-security.ipsmart.app/api/security/latest'), true);
foreach ($r['data'] as $v) {
echo $v['severidad'], ' ', $v['cveId'], ' ', $v['titulo'], PHP_EOL;
}
Ejemplo · Goresp, err := http.Get("https://api-security.ipsmart.app/api/security/latest")
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
var out map[string]any
json.NewDecoder(resp.Body).Decode(&out)
fmt.Println(out["total"], "vulnerabilidades")
for _, v := range out["data"].([]any) {
fila := v.(map[string]any)
fmt.Println(fila["severidad"], fila["cveId"], fila["titulo"])
}
Ejemplo · JavaHttpClient c = HttpClient.newHttpClient();
HttpRequest r = HttpRequest.newBuilder(
URI.create("https://api-security.ipsmart.app/api/security/latest")).build();
HttpResponse<String> resp = c.send(r, BodyHandlers.ofString());
System.out.println(resp.body());
Ejemplo · C#using var http = new HttpClient();
var json = await http.GetStringAsync("https://api-security.ipsmart.app/api/security/latest");
using var doc = JsonDocument.Parse(json);
Console.WriteLine(doc.RootElement.GetProperty("total"));
Ejemplo · Rubyrequire "net/http"
require "json"
body = Net::HTTP.get(URI("https://api-security.ipsmart.app/api/security/latest"))
JSON.parse(body)["data"].each { |v| puts "#{v['severidad']} #{v['cveId']} #{v['titulo']}" }
GET
/api/security/latest
Requiere token
Reglas de pentest en Markdown, con token
La misma ruta con cabecera Authorization devuelve otra cosa: el documento de reglas de pentest del día en Markdown, generado a partir de las vulnerabilidades más graves. Es lo que consume un agente para saber qué probar hoy. Guarde el valor de x-rules-hash: si no cambió, el documento es el mismo y no hace falta reprocesarlo.
Ejemplo
Ejemplo · cURLcurl -s -H "Authorization: Bearer $API_SECURITY_TOKEN" https://api-security.ipsmart.app/api/security/latest -o reglas.md -D cabeceras.txt
Ejemplo · Node.jsconst r = await fetch('https://api-security.ipsmart.app/api/security/latest', {
headers: { Authorization: 'Bearer ' + process.env.API_SECURITY_TOKEN },
});
console.log(r.headers.get('x-rules-hash'));
console.log(await r.text());
Ejemplo · JavaScript (navegador)// El token no puede vivir en el navegador: quien abre la pagina lo lee.
// Su servidor habla con api-security, y el navegador habla con su servidor.
const r = await fetch('/api/reglas', { credentials: 'same-origin' });
document.querySelector('#reglas').textContent = await r.text();
Ejemplo · Pythonimport os, requests
r = requests.get(
"https://api-security.ipsmart.app/api/security/latest",
headers={"Authorization": "Bearer " + os.environ["API_SECURITY_TOKEN"]},
timeout=30,
)
print(r.headers["x-rules-hash"])
print(r.text)
Ejemplo · PHP<?php
$ch = curl_init('https://api-security.ipsmart.app/api/security/latest');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . getenv('API_SECURITY_TOKEN')]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$markdown = curl_exec($ch);
curl_close($ch);
echo $markdown;
Ejemplo · Goreq, _ := http.NewRequest("GET", "https://api-security.ipsmart.app/api/security/latest", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_SECURITY_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
md, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Header.Get("x-rules-hash"))
os.WriteFile("reglas.md", md, 0o600)
Ejemplo · JavaHttpRequest r = HttpRequest.newBuilder(
URI.create("https://api-security.ipsmart.app/api/security/latest"))
.header("Authorization", "Bearer " + System.getenv("API_SECURITY_TOKEN"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(r, BodyHandlers.ofString());
System.out.println(resp.headers().firstValue("x-rules-hash").orElse("sin hash"));
Files.writeString(Path.of("reglas.md"), resp.body());
Ejemplo · C#using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("API_SECURITY_TOKEN"));
var resp = await http.GetAsync("https://api-security.ipsmart.app/api/security/latest");
Console.WriteLine(resp.Headers.GetValues("x-rules-hash").First());
await File.WriteAllTextAsync("reglas.md", await resp.Content.ReadAsStringAsync());
Ejemplo · Rubyrequire "net/http"
uri = URI("https://api-security.ipsmart.app/api/security/latest")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('API_SECURITY_TOKEN')}"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res["x-rules-hash"]
File.write("reglas.md", res.body)
GET
/api/security/rules
Requiere token
El Markdown sin negociación de contenido
Para clientes que solo quieren el fichero y no quieren depender de si mandaron o no la cabecera. Sin token responde 401, nunca contenido público. Es la ruta recomendada para un cron o un agente de sincronización: si un día el token caduca, el fallo es ruidoso en vez de silencioso.
Ejemplo
Ejemplo · cURLcurl -sS -f -H "Authorization: Bearer $API_SECURITY_TOKEN" https://api-security.ipsmart.app/api/security/rules > reglas.md
Ejemplo · Node.jsconst r = await fetch('https://api-security.ipsmart.app/api/security/rules', {
headers: { Authorization: 'Bearer ' + process.env.API_SECURITY_TOKEN },
});
if (!r.ok) throw new Error('api-security respondio ' + r.status);
await writeFile('reglas.md', await r.text());
Ejemplo · JavaScript (navegador)// Igual que arriba: desde el navegador nunca sale la cabecera Authorization.
// Su backend descarga el documento y lo sirve a quien ya tenga sesion abierta.
const r = await fetch('/api/reglas', { credentials: 'same-origin' });
if (!r.ok) throw new Error('su backend respondio ' + r.status);
document.querySelector('#reglas').textContent = await r.text();
Ejemplo · Pythonimport os, requests
r = requests.get(
"https://api-security.ipsmart.app/api/security/rules",
headers={"Authorization": "Bearer " + os.environ["API_SECURITY_TOKEN"]},
timeout=30,
)
r.raise_for_status()
open("reglas.md", "w", encoding="utf-8").write(r.text)
Ejemplo · PHP<?php
$ch = curl_init('https://api-security.ipsmart.app/api/security/rules');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('API_SECURITY_TOKEN')],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$md = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) {
throw new RuntimeException('api-security no devolvio las reglas');
}
file_put_contents('reglas.md', $md);
Ejemplo · Goreq, _ := http.NewRequest("GET", "https://api-security.ipsmart.app/api/security/rules", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_SECURITY_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
log.Fatal("api-security respondio ", resp.Status)
}
md, _ := io.ReadAll(resp.Body)
os.WriteFile("reglas.md", md, 0o600)
Ejemplo · JavaHttpRequest r = HttpRequest.newBuilder(
URI.create("https://api-security.ipsmart.app/api/security/rules"))
.header("Authorization", "Bearer " + System.getenv("API_SECURITY_TOKEN"))
.timeout(Duration.ofSeconds(30))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(r, BodyHandlers.ofString());
if (resp.statusCode() != 200) throw new IllegalStateException("HTTP " + resp.statusCode());
Files.writeString(Path.of("reglas.md"), resp.body());
Ejemplo · C#using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("API_SECURITY_TOKEN"));
var resp = await http.GetAsync("https://api-security.ipsmart.app/api/security/rules");
resp.EnsureSuccessStatusCode();
await File.WriteAllTextAsync("reglas.md", await resp.Content.ReadAsStringAsync());
Ejemplo · Rubyrequire "net/http"
uri = URI("https://api-security.ipsmart.app/api/security/rules")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('API_SECURITY_TOKEN')}"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
raise "api-security respondio #{res.code}" unless res.code == "200"
File.write("reglas.md", res.body)
POST
/api/security/sync
Requiere token
Fuerza la sincronización con las fuentes
Dispara a mano lo que el servicio hace solo al arrancar: consultar las fuentes públicas de vulnerabilidades y regenerar el documento de reglas. Úselo cuando no quiera esperar al ciclo automático. No lo llame en bucle: cada llamada golpea a las fuentes externas y estas aplican límite de peticiones.
Ejemplo
Ejemplo · cURLcurl -sS -X POST -H "Authorization: Bearer $API_SECURITY_TOKEN" https://api-security.ipsmart.app/api/security/sync
Ejemplo · Node.jsconst r = await fetch('https://api-security.ipsmart.app/api/security/sync', {
method: 'POST',
headers: { Authorization: 'Bearer ' + process.env.API_SECURITY_TOKEN },
});
const res = await r.json();
console.log(res.obtenidas, 'obtenidas, fallaron', res.fuentesFallidas.length);
Ejemplo · JavaScript (navegador)// Sincronizar es una accion privilegiada: va por su backend, con la sesion
// del usuario y con proteccion CSRF. El navegador no dispara esto directamente.
const r = await fetch('/api/reglas/sincronizar', {
method: 'POST',
credentials: 'same-origin',
headers: { 'X-CSRF-Token': tokenCsrfDeSuFormulario },
});
console.log(await r.json());
Ejemplo · Pythonimport os, requests
r = requests.post(
"https://api-security.ipsmart.app/api/security/sync",
headers={"Authorization": "Bearer " + os.environ["API_SECURITY_TOKEN"]},
timeout=60,
)
print(r.json())
Ejemplo · PHP<?php
$ch = curl_init('https://api-security.ipsmart.app/api/security/sync');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('API_SECURITY_TOKEN')],
CURLOPT_RETURNTRANSFER => true,
]);
print_r(json_decode(curl_exec($ch), true));
Ejemplo · Goreq, _ := http.NewRequest("POST", "https://api-security.ipsmart.app/api/security/sync", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_SECURITY_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
Ejemplo · JavaHttpRequest r = HttpRequest.newBuilder(
URI.create("https://api-security.ipsmart.app/api/security/sync"))
.header("Authorization", "Bearer " + System.getenv("API_SECURITY_TOKEN"))
.POST(BodyPublishers.noBody())
.build();
System.out.println(HttpClient.newHttpClient().send(r, BodyHandlers.ofString()).body());
Ejemplo · C#using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("API_SECURITY_TOKEN"));
var resp = await http.PostAsync("https://api-security.ipsmart.app/api/security/sync", null);
Console.WriteLine(await resp.Content.ReadAsStringAsync());
Ejemplo · Rubyrequire "net/http"
uri = URI("https://api-security.ipsmart.app/api/security/sync")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch('API_SECURITY_TOKEN')}"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.body