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 sides:
fighter_1is the first fighterfighter_2is the second fighter
Each fighter needs skills and passives arrays plus a fallback_skill.
Both arrays may be empty. The battle engine uses the fallback skill when the
fighter has no active skills or cannot afford the next skill in its rotation.
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",
"health": 1200,
"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,
"health_regen_1": 0,
"health_regen_2": 0,
"energy_regen_1": 0,
"energy_regen_2": 0,
"passives": [],
"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",
"health": 1000,
"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,
"health_regen_1": 0,
"health_regen_2": 0,
"energy_regen_1": 0,
"energy_regen_2": 0,
"passives": [],
"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"
}
]
}
}
}'
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 passives
when your battle design needs them.
Try different outcomes
Change 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 fighter who won |
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.
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: