← Back to Articles Directory
AI Models • August 12, 2026 •Updated September 27, 2026 • 4 min read

DeepSeek V4 Pro 0813: Current API Specs, Pricing, and Coding Samples

A source-based summary of the current API model version and its time- and cache-dependent prices, with archived coding examples.

Co-Founder & Lead Programmer of AcceleratedLogic AI

DeepSeek's API documentation currently identifies the Pro endpoint version as DeepSeek-V4-Pro-0813. This guide summarizes the current official model and pricing documentation, then keeps two coding examples from an earlier AcceleratedLogic prompt trial. The examples are not an independent comparison or a claim that this model ranks above competitors.

Current model and API facts

The DeepSeek V4 model card describes Pro as a 1.6-trillion-parameter mixture-of-experts model with 49 billion parameters active per token, a one-million-token context window, and text input. DeepSeek's API model and pricing page lists the current Pro version as DeepSeek-V4-Pro-0813 and an API context limit of one million tokens, with a maximum output of 384,000 tokens.
The listed API price varies by time and cache status. The page currently lists Pro cache-miss input at $0.66 per million tokens off-peak and $1.32 at peak, cached input at $0.022 off-peak and $0.044 at peak, and output at $1.98 off-peak and $3.96 at peak. Off-peak pricing is half of peak pricing under the schedule described by DeepSeek. These rates supersede the older flat price stated in the original article; check the live pricing page before estimating cost.

Archived coding examples

The earlier trial used two self-contained HTML prompts: one for a glass sphere with an origami crane, and one for an interactive Three.js globe. The original page retained the generated source but did not preserve a versioned test harness, repeat runs, or a formal rubric. Treat the snippets as inspectable examples, not as measured rankings.

SVG illustration sample

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Glass Sphere with Origami Crane</title>
<style>
  html, body { margin:0; padding:0; height:100%; overflow:hidden;
    background: radial-gradient(circle at 50% 38%, #1c2233 0%, #0c0f1a 55%, #04050b 100%); }
  body { display:flex; align-items:center; justify-content:center; }
  svg { display:block; width:min(92vmin, 900px); height:auto; }
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" role="img" aria-label="Photorealistic glass sphere containing an origami crane">
  <defs>
    <filter id="blur2" x="-40%" y="-40%" width="180%" height="180%"><feGaussianBlur stdDeviation="2"/></filter>
    <filter id="blur6" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="6"/></filter>
    <filter id="blur14" x="-70%" y="-70%" width="240%" height="240%"><feGaussianBlur stdDeviation="14"/></filter>
    <filter id="blur30" x="-100%" y="-100%" width="300%" height="300%"><feGaussianBlur stdDeviation="30"/></filter>
    <radialGradient id="backGlow" cx="0.5" cy="0.5" r="0.5">
      <stop offset="0" stop-color="#8fb4e0" stop-opacity="0.16"/>
      <stop offset="0.65" stop-color="#7fa6d4" stop-opacity="0.05"/>
      <stop offset="1" stop-color="#000000" stop-opacity="0"/>
    </radialGradient>
    <radialGradient id="groundShadow" cx="0.5" cy="0.5" r="0.5">
      <stop offset="0" stop-color="#000000" stop-opacity="0.6"/>
      <stop offset="0.5" stop-color="#000000" stop-opacity="0.3"/>
      <stop offset="1" stop-color="#000000" stop-opacity="0"/>
    </radialGradient>
    <radialGradient id="caustic" cx="0.5" cy="0.5" r="0.5">
      <stop offset="0" stop-color="#c9ecff" stop-opacity="0.5"/>
      <stop offset="0.55" stop-color="#8fc6f2" stop-opacity="0.16"/>
      <stop offset="1" stop-color="#7fb8e8" stop-opacity="0"/>
    </radialGradient>
    <linearGradient id="wL1" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#ffffff"/>
      <stop offset="0.55" stop-color="#f7f2e6"/>
      <stop offset="1" stop-color="#e2d8c3"/>
    </linearGradient>
    <linearGradient id="wL2" x1="0" y1="1" x2="1" y2="0">
      <stop offset="0" stop-color="#ddd3bb"/>
      <stop offset="1" stop-color="#efe7d5"/>
    </linearGradient>
    <linearGradient id="wR1" x1="1" y1="0" x2="0" y2="1">
      <stop offset="0" stop-color="#fbf8ef"/>
      <stop offset="1" stop-color="#d6cbb1"/>
    </linearGradient>
    <linearGradient id="wR2" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#cdc2a8"/>
      <stop offset="1" stop-color="#e4dbc6"/>
    </linearGradient>
    <linearGradient id="bodyL" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#f6f1e2"/>
      <stop offset="1" stop-color="#d7ccb2"/>
    </linearGradient>
    <linearGradient id="bodyR" x1="1" y1="0" x2="0" y2="1">
      <stop offset="0" stop-color="#c9bda1"/>
      <stop offset="1" stop-color="#dfd5bd"/>
    </linearGradient>
    <linearGradient id="neckG" x1="0" y1="1" x2="0" y2="0">
      <stop offset="0" stop-color="#e2d8c1"/>
      <stop offset="1" stop-color="#f9f5ea"/>
    </linearGradient>
    <linearGradient id="headG" x1="0" y1="1" x2="0" y2="0">
      <stop offset="0" stop-color="#ece4d1"/>
      <stop offset="1" stop-color="#fbf8ef"/>
    </linearGradient>
    <linearGradient id="beakG" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0" stop-color="#e7dec9"/>
      <stop offset="1" stop-color="#b3a383"/>
    </linearGradient>
    <linearGradient id="tailG" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0" stop-color="#e9e0cb"/>
      <stop offset="1" stop-color="#bfb292"/>
    </linearGradient>
    <radialGradient id="glassFill" cx="0.45" cy="0.38" r="0.75">
      <stop offset="0" stop-color="#cfeaff" stop-opacity="0.05"/>
      <stop offset="0.55" stop-color="#bfe2ff" stop-opacity="0.11"/>
      <stop offset="0.82" stop-color="#a3d0f7" stop-opacity="0.24"/>
      <stop offset="0.94" stop-color="#7fb4e8" stop-opacity="0.42"/>
      <stop offset="1" stop-color="#5e97d4" stop-opacity="0.66"/>
    </radialGradient>
    <linearGradient id="rimLight" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#ffffff" stop-opacity="0.95"/>
      <stop offset="0.25" stop-color="#d7ecff" stop-opacity="0.55"/>
      <stop offset="0.55" stop-color="#8fb8e8" stop-opacity="0.28"/>
      <stop offset="0.8" stop-color="#5e94cc" stop-opacity="0.18"/>
      <stop offset="1" stop-color="#4a7cb8" stop-opacity="0.38"/>
    </linearGradient>
    <clipPath id="sphereClip"><circle cx="400" cy="420" r="264"/></clipPath>
  </defs>

  <!-- backdrop & floor -->
  <circle cx="400" cy="420" r="360" fill="url(#backGlow)"/>
  <ellipse cx="400" cy="700" rx="220" ry="40" fill="url(#groundShadow)" filter="url(#blur30)"/>
  <ellipse cx="400" cy="692" rx="120" ry="22" fill="url(#caustic)" filter="url(#blur14)"/>

  <!-- ambient occlusion behind crane -->
  <ellipse cx="400" cy="470" rx="150" ry="110" fill="#081020" opacity="0.22" filter="url(#blur30)"/>

  <!-- ===== ORIGAMI CRANE ===== -->
  <g id="crane">
    <polygon points="400,420 340,475 400,565" fill="url(#bodyL)" stroke="#d8cdb3" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,420 460,475 400,565" fill="url(#bodyR)" stroke="#c5b99e" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,420 245,300 289,389" fill="url(#wL1)" stroke="#e0d6c0" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,420 289,389 332,478" fill="url(#wL2)" stroke="#cbbfa3" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,420 555,300 511,389" fill="url(#wR1)" stroke="#ddd3bb" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,420 511,389 468,478" fill="url(#wR2)" stroke="#c2b69a" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="394,420 397,320 403,320 406,420" fill="url(#neckG)" stroke="#d3c7ab" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="400,292 405,307 400,322 395,307" fill="url(#headG)" stroke="#d8ccb2" stroke-width="0.7" stroke-linejoin="round"/>
    <polygon points="405,307 424,300 401,299" fill="url(#beakG)" stroke="#b3a383" stroke-width="0.6" stroke-linejoin="round"/>
    <polygon points="388,566 412,566 400,620" fill="url(#tailG)" stroke="#bfb292" stroke-width="0.7" stroke-linejoin="round"/>
    <g stroke="#b3a483" stroke-opacity="0.55" stroke-width="1" fill="none" stroke-linecap="round">
      <line x1="400" y1="420" x2="400" y2="565"/>
      <line x1="400" y1="420" x2="289" y2="389"/>
      <line x1="400" y1="420" x2="511" y2="389"/>
    </g>
  </g>

  <!-- ===== GLASS SPHERE ===== -->
  <circle cx="400" cy="420" r="264" fill="url(#glassFill)"/>

  <g clip-path="url(#sphereClip)">
    <ellipse cx="400" cy="668" rx="80" ry="30" fill="#cfeaff" opacity="0.22" filter="url(#blur14)"/>
    <use href="#crane" transform="translate(0 700) scale(1 -0.4)" opacity="0.06" filter="url(#blur6)"/>
    <path d="M250,235 A 240 240 0 0 1 470,180" fill="none" stroke="#ffffff" stroke-opacity="0.35" stroke-width="26" stroke-linecap="round" filter="url(#blur14)"/>
    <path d="M330,205 A 250 250 0 0 1 520,205" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="16" stroke-linecap="round" filter="url(#blur14)"/>
  </g>

  <circle cx="400" cy="420" r="256" fill="none" stroke="#7fb4e8" stroke-opacity="0.22" stroke-width="10" filter="url(#blur6)"/>
  <ellipse cx="508" cy="560" rx="42" ry="22" fill="#ffffff" opacity="0.32" filter="url(#blur6)" transform="rotate(-38 508 560)"/>
  <ellipse cx="300" cy="288" rx="92" ry="50" fill="#ffffff" opacity="0.85" filter="url(#blur14)" transform="rotate(-32 300 288)"/>
  <ellipse cx="298" cy="286" rx="44" ry="22" fill="#ffffff" opacity="0.95" filter="url(#blur6)" transform="rotate(-32 298 286)"/>
  <circle cx="400" cy="420" r="264" fill="none" stroke="url(#rimLight)" stroke-width="3" filter="url(#blur2)"/>
  <circle cx="400" cy="420" r="263" fill="none" stroke="#ffffff" stroke-opacity="0.5" stroke-width="1.1" opacity="0.7"/>
</svg>
</body>
</html>
For a creative code task, assess whether the requested subject is recognizable and whether the output renders without relying on missing assets. A single visual result cannot establish broader coding reliability.

Three.js globe sample

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Procedural 3D Globe</title>
<style>
  html, body { margin: 0; height: 100%; overflow: hidden; background: #04060f; }
  body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
  #container { position: fixed; inset: 0; }
  #container canvas { display: block; }
  #ui {
    position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
    display: flex; align-items: center; gap: 14px;
    padding: 12px 20px; border-radius: 999px;
    background: rgba(14, 20, 38, 0.72);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
    border: 1px solid rgba(120, 160, 220, 0.25);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
    color: #cdd9f2; font-size: 14px; letter-spacing: 0.02em;
    user-select: none;
  }
  #ui input[type="range"] { width: 220px; accent-color: #4da3ff; cursor: pointer; }
  #ui .value { min-width: 42px; text-align: right; font-variant-numeric: tabular-nums; color: #fff; }
</style>
</head>
<body>
<div id="container"></div>
<div id="ui">
  <span>Rotation speed</span>
  <input id="speed" type="range" min="0" max="3" step="0.01" value="0.6" aria-label="Rotation speed">
  <span id="speedVal" class="value">0.60</span>
</div>
<script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
  }
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const container = document.getElementById('container');

// ---------- renderer / scene / camera ----------
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, container.clientWidth / container.clientHeight, 0.1, 120);
camera.position.set(0, 0.7, 3.4);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setClearColor(0x04060f, 1);
renderer.outputColorSpace = THREE.SRGBColorSpace;
container.appendChild(renderer.domElement);

// ---------- lights ----------
scene.add(new THREE.AmbientLight(0x3c4c6e, 1.4));
const sun = new THREE.DirectionalLight(0xffffff, 2.6);
sun.position.set(5, 2.2, 4);
scene.add(sun);

// ---------- starfield ----------
{
  const N = 900;
  const pos = new Float32Array(N * 3);
  for (let i = 0; i < N; i++) {
    const t = Math.random() * Math.PI * 2;
    const p = Math.acos(2 * Math.random() - 1);
    const r = 55;
    pos[i * 3]     = r * Math.sin(p) * Math.cos(t);
    pos[i * 3 + 1] = r * Math.sin(p) * Math.sin(t);
    pos[i * 3 + 2] = r * Math.cos(p);
  }
  const g = new THREE.BufferGeometry();
  g.setAttribute('position', new THREE.BufferAttribute(pos, 3));
  const m = new THREE.PointsMaterial({
    color: 0xffffff, size: 1.8, sizeAttenuation: false,
    transparent: true, opacity: 0.85, depthWrite: false
  });
  scene.add(new THREE.Points(g, m));
}

// ---------- procedural noise (3D value noise + fbm) ----------
function hash3(x, y, z) {
  let h = Math.imul(x, 0x1F1F1F1F) ^ Math.imul(y, 0x9E3779B9) ^ Math.imul(z, 0x85EBCA77);
  h = Math.imul(h ^ (h >>> 15), 0x85EBCA6B);
  h = Math.imul(h ^ (h >>> 13), 0xC2B2AE35);
  h ^= h >>> 16;
  return (h >>> 0) / 4294967296;
}
function valueNoise3(x, y, z) {
  const x0 = Math.floor(x), y0 = Math.floor(y), z0 = Math.floor(z);
  const tx = x - x0, ty = y - y0, tz = z - z0;
  const sx = tx * tx * (3 - 2 * tx);
  const sy = ty * ty * (3 - 2 * ty);
  const sz = tz * tz * (3 - 2 * tz);
  const c000 = hash3(x0, y0, z0),           c100 = hash3(x0 + 1, y0, z0);
  const c010 = hash3(x0, y0 + 1, z0),       c110 = hash3(x0 + 1, y0 + 1, z0);
  const c001 = hash3(x0, y0, z0 + 1),       c101 = hash3(x0 + 1, y0, z0 + 1);
  const c011 = hash3(x0, y0 + 1, z0 + 1),   c111 = hash3(x0 + 1, y0 + 1, z0 + 1);
  const x00 = c000 + (c100 - c000) * sx;
  const x10 = c010 + (c110 - c010) * sx;
  const x01 = c001 + (c101 - c001) * sx;
  const x11 = c011 + (c111 - c011) * sx;
  const y0i = x00 + (x10 - x00) * sy;
  const y1i = x01 + (x11 - x01) * sy;
  return y0i + (y1i - y0i) * sz;
}
function fbm3(x, y, z, octaves) {
  let sum = 0, amp = 0.5, freq = 1, norm = 0;
  for (let o = 0; o < octaves; o++) {
    sum += (valueNoise3(x * freq, y * freq, z * freq) * 2 - 1) * amp;
    norm += amp;
    amp *= 0.5;
    freq *= 2;
  }
  return sum / norm;
}
// ---------- procedural textures ----------
const lerp3 = (a, b, t) => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
function ramp(stops, t) {
  for (let i = 0; i < stops.length - 1; i++) {
    const t0 = stops[i][0], c0 = stops[i][1];
    const t1 = stops[i + 1][0], c1 = stops[i + 1][1];
    if (t <= t1) {
      const f = Math.min(1, Math.max(0, (t - t0) / (t1 - t0)));
      return lerp3(c0, c1, f);
    }
  }
  return stops[stops.length - 1][1];
}
const landRamp = (t) => ramp([
  [0.00, [0.16, 0.42, 0.16]],
  [0.30, [0.34, 0.54, 0.28]],
  [0.58, [0.56, 0.48, 0.30]],
  [0.80, [0.46, 0.39, 0.29]],
  [0.92, [0.62, 0.60, 0.58]],
  [1.00, [0.96, 0.97, 1.00]]
], t);
const oceanRamp = (d) => ramp([
  [0.00, [0.10, 0.30, 0.55]],
  [0.35, [0.07, 0.22, 0.45]],
  [1.00, [0.03, 0.10, 0.26]]
], d);

function generateTextures() {
  const W = 1024, H = 512;
  const colorC = document.createElement('canvas'); colorC.width = W; colorC.height = H;
  const specC  = document.createElement('canvas'); specC.width = W; specC.height = H;
  const bumpC  = document.createElement('canvas'); bumpC.width = W; bumpC.height = H;
  const ctx = colorC.getContext('2d'), sctx = specC.getContext('2d'), bctx = bumpC.getContext('2d');
  const img = ctx.createImageData(W, H), simg = sctx.createImageData(W, H), bimg = bctx.createImageData(W, H);
  const d = img.data, sd = simg.data, bd = bimg.data;

  const scale = 1.6, octaves = 4, seaLevel = 0.08;

  for (let y = 0; y < H; y++) {
    const v = y / (H - 1);
    const phi = v * Math.PI;
    const sinPhi = Math.sin(phi), cosPhi = Math.cos(phi);
    const lat = 90 - v * 180;
    const polar = Math.min(1, Math.max(0, (Math.abs(lat) - 62) / 20));
    for (let x = 0; x < W; x++) {
      const u = x / W;
      const th = u * Math.PI * 2;
      const nx = sinPhi * Math.cos(th), ny = cosPhi, nz = sinPhi * Math.sin(th);
      const e = fbm3(nx * scale, ny * scale, nz * scale, octaves);
      const i = (y * W + x) * 4;
      let r, g, b, spec, bump;
      if (e > seaLevel) {
        const t = Math.min(1, (e - seaLevel) / (1 - seaLevel));
        const c = lerp3(landRamp(t), [0.96, 0.98, 1.0], polar);
        r = c[0]; g = c[1]; b = c[2];
        spec = 0.0;
        bump = 0.35 + 0.65 * t;
      } else {
        const depth = Math.min(1, Math.max(0, (seaLevel - e) / (seaLevel + 1)));
        const c = lerp3(oceanRamp(depth), [0.86, 0.91, 0.96], polar);
        r = c[0]; g = c[1]; b = c[2];
        spec = 1.0;
        bump = 0.2;
      }
      d[i] = Math.round(r * 255); d[i + 1] = Math.round(g * 255); d[i + 2] = Math.round(b * 255); d[i + 3] = 255;
      const sv = Math.round(spec * 255);
      sd[i] = sv; sd[i + 1] = sv; sd[i + 2] = sv; sd[i + 3] = 255;
      const bv = Math.round(bump * 255);
      bd[i] = bv; bd[i + 1] = bv; bd[i + 2] = bv; bd[i + 3] = 255;
    }
  }
  ctx.putImageData(img, 0, 0);
  sctx.putImageData(simg, 0, 0);
  bctx.putImageData(bimg, 0, 0);

  const colorMap = new THREE.CanvasTexture(colorC);
  colorMap.colorSpace = THREE.SRGBColorSpace;
  colorMap.anisotropy = Math.min(8, renderer.capabilities.getMaxAnisotropy());
  const specularMap = new THREE.CanvasTexture(specC);
  const bumpMap = new THREE.CanvasTexture(bumpC);
  return { colorMap, specularMap, bumpMap };
}

// ---------- globe ----------
const GLOBE_R = 1.0;
const { colorMap, specularMap, bumpMap } = generateTextures();
const globe = new THREE.Mesh(
  new THREE.SphereGeometry(GLOBE_R, 128, 128),
  new THREE.MeshPhongMaterial({
    map: colorMap,
    specularMap: specularMap,
    specular: new THREE.Color(0xffffff),
    shininess: 22,
    bumpMap: bumpMap,
    bumpScale: 0.02
  })
);
scene.add(globe);

// ---------- translucent atmosphere glow ----------
const atmosphere = new THREE.Mesh(
  new THREE.SphereGeometry(GLOBE_R * 1.16, 96, 96),
  new THREE.ShaderMaterial({
    vertexShader: [
      "varying vec3 vNormal;",
      "varying vec3 vView;",
      "void main() {",
      "  vec4 mv = modelViewMatrix * vec4(position, 1.0);",
      "  vView = normalize(-mv.xyz);",
      "  vNormal = normalize(normalMatrix * normal);",
      "  gl_Position = projectionMatrix * mv;",
      "}"
    ].join("\n"),
    fragmentShader: [
      "varying vec3 vNormal;",
      "varying vec3 vView;",
      "void main() {",
      "  float fres = pow(1.0 - abs(dot(vNormal, vView)), 3.0);",
      "  gl_FragColor = vec4(vec3(0.28, 0.55, 1.0) * fres, fres);",
      "}"
    ].join("\n"),
    side: THREE.BackSide,
    blending: THREE.AdditiveBlending,
    transparent: true,
    depthWrite: false
  })
);
scene.add(atmosphere);
// ---------- orbiting ring of light particles ----------
function makeGlowSprite() {
  const c = document.createElement('canvas');
  c.width = c.height = 64;
  const g = c.getContext('2d');
  const grd = g.createRadialGradient(32, 32, 0, 32, 32, 32);
  grd.addColorStop(0, 'rgba(255,255,255,1)');
  grd.addColorStop(0.35, 'rgba(255,255,255,0.85)');
  grd.addColorStop(1, 'rgba(255,255,255,0)');
  g.fillStyle = grd;
  g.fillRect(0, 0, 64, 64);
  return new THREE.CanvasTexture(c);
}

const ringGroup = new THREE.Group();
{
  const N = 800;
  const pos = new Float32Array(N * 3);
  const col = new Float32Array(N * 3);
  const R = GLOBE_R * 1.55;
  const c1 = new THREE.Color(0x4db6ff);
  const c2 = new THREE.Color(0xffffff);
  for (let i = 0; i < N; i++) {
    const th = (i / N) * Math.PI * 2;
    const rr = R + (Math.random() - 0.5) * 0.08;
    const yy = (Math.random() - 0.5) * 0.14;
    pos[i * 3] = Math.cos(th) * rr;
    pos[i * 3 + 1] = yy;
    pos[i * 3 + 2] = Math.sin(th) * rr;
    const tmp = c1.clone().lerp(c2, Math.random());
    col[i * 3] = tmp.r; col[i * 3 + 1] = tmp.g; col[i * 3 + 2] = tmp.b;
  }
  const g = new THREE.BufferGeometry();
  g.setAttribute('position', new THREE.BufferAttribute(pos, 3));
  g.setAttribute('color', new THREE.BufferAttribute(col, 3));
  const m = new THREE.PointsMaterial({
    size: 0.09,
    map: makeGlowSprite(),
    vertexColors: true,
    blending: THREE.AdditiveBlending,
    depthWrite: false,
    transparent: true,
    sizeAttenuation: true
  });
  ringGroup.add(new THREE.Points(g, m));
}
ringGroup.rotation.x = 0.45;
scene.add(ringGroup);

// ---------- controls (drag rotate + zoom) ----------
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.08;
controls.rotateSpeed = 0.55;
controls.zoomSpeed = 1.0;
controls.enablePan = false;
controls.minDistance = 1.6;
controls.maxDistance = 8;
controls.target.set(0, 0, 0);

// ---------- rotation speed slider ----------
let rotationSpeed = 0.6;
const slider = document.getElementById('speed');
const speedVal = document.getElementById('speedVal');
slider.addEventListener('input', () => {
  rotationSpeed = parseFloat(slider.value);
  speedVal.textContent = rotationSpeed.toFixed(2);
});

// ---------- resize ----------
window.addEventListener('resize', () => {
  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.clientWidth, container.clientHeight);
});

// ---------- render loop ----------
const clock = new THREE.Clock();
function animate() {
  requestAnimationFrame(animate);
  const dt = Math.min(clock.getDelta(), 0.1);
  globe.rotation.y += rotationSpeed * dt;
  ringGroup.rotation.y += dt * 0.12;
  controls.update();
  renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
Interactive outputs should be opened in a browser and checked for console errors, input handling, and resizing. The snippet preserves the original trial output so readers can inspect it, but this article does not claim those checks were repeated against the current API version.

How to evaluate the API for your work

Before choosing V4 Pro, run representative prompts with the same input files, tools, and success criteria you would use for another model. Record the exact model version, cache state, time window, reasoning mode, token usage, and latency. Compare quality and cost together; changing peak/off-peak rates and cache hits can materially alter the bill for a long-context workflow.