Skip to content

POST /v1/render — Submit Render

POST /v1/render

Upload an osu! replay file (.osr) with rendering parameters to queue a render job. Returns a job_id for tracking.

Rate Limit: 5 requests per minute per IP

Request

Content-Type: multipart/form-data

Parameters

FieldTypeRequiredDefaultDescription
replayFileThe .osr replay file
skinstringDefaultSkin name (alphanumeric, spaces, hyphens, underscores only)
bg_dimfloat0.95Background dim (0.0 = none, 1.0 = full). Values > 1.0 are auto-normalized (e.g., 950.95)
resolutionstring1080pOutput resolution: 1080p or 4k
motion_blurbooltrueEnable motion blur
storyboardbooltrueLoad beatmap storyboard
videoboolfalseLoad beatmap background video
snaking_inbooltrueSlider snaking-in animation
snaking_outbooltrueSlider snaking-out animation
hit_error_meterbooltrueShow hit error meter overlay
key_overlaybooltrueShow key press overlay

Example

bash
curl -X POST http://localhost:8727/v1/render \
  -F "replay=@my_replay.osr" \
  -F "skin=WhiteCat 1.0" \
  -F "resolution=1080p" \
  -F "bg_dim=0.95" \
  -F "motion_blur=true" \
  -F "storyboard=true" \
  -F "video=false"
python
import httpx

with open("my_replay.osr", "rb") as f:
    resp = httpx.post(
        "http://localhost:8727/v1/render",
        files={"replay": ("replay.osr", f)},
        data={
            "skin": "WhiteCat 1.0",
            "resolution": "1080p",
            "bg_dim": "0.95",
        },
    )
print(resp.json())

Response

Status: 202 Accepted

json
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued",
  "links": {
    "status": "/v1/jobs/550e8400-e29b-41d4-a716-446655440000"
  }
}

Validation Rules

The endpoint performs extensive validation before accepting a job:

File Validation

  • Extension: Must end in .osr
  • Size: Must not exceed MAX_REPLAY_SIZE_MB (default 50 MB)
  • Not empty: File size must be > 0
  • Structure: Parsed with osrparse to verify replay integrity
  • Game mode: Only osu!standard replays (mode 0) are supported

Parameter Validation

  • Skin name: Must match regex ^[a-zA-Z0-9_ -]+$
  • Resolution: Must be 1080p or 4k
  • bg_dim: Must be between 0.0 and 1.0 (auto-normalized if > 1.0)

Capacity Checks

  • Global queue: Rejects if MAX_QUEUED (100) jobs are already queued
  • Global rendering: Rejects if MAX_RENDERING (20) jobs are rendering
  • Per-IP limit: Maximum 2 active jobs per IP (enforced via pg_advisory_xact_lock)

Error Responses

StatusConditionDetail
400Missing/wrong file extensionFile must be an osu! replay (.osr) file.
400Empty fileUploaded replay file is empty.
413File too largeReplay file exceeds maximum size of 50MB.
415Invalid replay structureInvalid replay file. The structure is corrupted or unsupported.
422Invalid skin name or parametersPydantic validation error
429Rate limit exceededRate limit exceeded: 5 per 1 minute
429Per-IP concurrent limitYou already have 2 active render jobs.
503Queue fullThe render queue is currently full. Please try again later.
503At capacityThe render infrastructure is at maximum capacity.

Admission Control Flow

Built with VitePress