Quick Start¶
Welcome to Cowculator! This guide walks you through running your first battle in just a few minutes.
Send two fighter definitions to POST /api/battle/start, then use the returned
battle result (BattleResult) to identify the winner or replay the battle from
its battle log.
Looking for exact fields?
Use the OpenAPI reference for the complete request and response schemas, defaults, and validation rules.
Send a battle request¶
The request body has two fighters and optional battle configuration:
fighter_1is the first fighterfighter_2is the second fighterconfigurationcontrols the turn limit and its result policy
Skill arrays and the fallback skill are optional. The battle engine uses the fallback when a fighter has no active skill or cannot afford the next one. If no fallback exists, that turn ends without a skill.
Replace YOUR_API_KEY with your Cowculator API key, then run:
curl -X POST "https://api.cowculator.dev/api/battle/start" \
-H "Content-Type: application/json" \
-H "X-COW-Key: YOUR_API_KEY" \
-d '{
"fighter_1": {
"fighter_id": "mighty-cow",
"name": "Mighty Cow",
"maximum_health": 1200,
"initial_health": 1000,
"maximum_energy": 40,
"initial_energy": 40,
"speed": 10,
"defence": 0,
"attack": 100,
"critical_damage": 1.1,
"critical_rate": 0,
"critical_resistance": 0,
"dot_reduction": 0,
"damage_reduction": 0,
"damage_multiplier": 1,
"regeneration": {
"health": [],
"energy": []
},
"passive_skills": [],
"active_skills": [
{
"skill_id": "headbutt",
"name": "Headbutt",
"chance": 1,
"actions": [
{
"type": "attack",
"name": "Headbutt hit",
"chance": 1,
"target_type": "enemy",
"damage_value": 1.2,
"damage_type": "normal"
}
],
"energy_cost": 20
}
],
"fallback_skill": {
"skill_id": "cow-basic-attack",
"name": "Basic Attack",
"chance": 1,
"actions": [
{
"type": "attack",
"name": "Basic Attack hit",
"chance": 1,
"target_type": "enemy",
"damage_value": 1,
"damage_type": "normal"
}
]
}
},
"fighter_2": {
"fighter_id": "wonder-dog",
"name": "Wonder Dog",
"maximum_health": 1000,
"maximum_energy": 40,
"speed": 12,
"defence": 0,
"attack": 90,
"critical_damage": 1.1,
"critical_rate": 0,
"critical_resistance": 0,
"dot_reduction": 0,
"damage_reduction": 0,
"damage_multiplier": 1,
"regeneration": {
"health": [],
"energy": []
},
"passive_skills": [],
"active_skills": [
{
"skill_id": "power-bite",
"name": "Power Bite",
"chance": 1,
"actions": [
{
"type": "attack",
"name": "Power Bite hit",
"chance": 1,
"target_type": "enemy",
"damage_value": 1.2,
"damage_type": "normal"
}
],
"energy_cost": 20
}
],
"fallback_skill": {
"skill_id": "dog-basic-attack",
"name": "Basic Attack",
"chance": 1,
"actions": [
{
"type": "attack",
"name": "Basic Attack hit",
"chance": 1,
"target_type": "enemy",
"damage_value": 1,
"damage_type": "normal"
}
]
}
},
"configuration": {
"max_turn": 40,
"turn_limit_result": "remaining_health_percentage"
}
}'
This example shows the complete fighter, active-skill, and attack-action shapes.
The API provides defaults for many of these fields, but keeping them visible
makes the starting configuration clear. Add passive skill objects to
passive_skills when your battle design needs them.
Try different outcomes
Change initial health, speed, attack, or damage_value, then send the
request again. Cowculator preserves chance-based mechanics, so battles with
chance values below 1 may play out differently.
Read the result¶
The response is a battle result represented by BattleResult. Start with these
fields:
| Field | What it tells you |
|---|---|
winner_id |
The ID of the winning fighter, or null for a draw |
fighter_1_id, fighter_1_name |
The identity of the first fighter |
fighter_2_id, fighter_2_name |
The identity of the second fighter |
total_turn |
The number of global battle turns processed |
battle_started |
When the battle started |
battle_end |
When the battle ended |
battle_event_logs |
The battle log used to inspect or replay the battle |
The response always includes the battle log in battle_event_logs, with fighter
snapshots and the events produced during the battle. See the
BattleResult guide for its complete structure and
examples.
Handle errors consistently¶
When a request fails, check its HTTP status and error code.
See Error Handling for codes, examples, and the change
from response.detail.
Explore what happened¶
Use winner_id when you only need the outcome. To build a replay, process
battle_event_logs.preparation, battle_event_logs.turns, and
battle_event_logs.battle_end in that order. Within each preparation entry or
turn, read the ordered fighter events by event_type and structured data
instead of parsing their display descriptions. For each turn, process its
turn-level events first. Then process energy regeneration, health
regeneration, and any natural status expiry in turn_end.events.
Next, learn how to: