Skip to content

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_1 is the first fighter
  • fighter_2 is 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: