diff --git a/config/api_platform/resources.xml b/config/api_platform/resources.xml
index 5f6a9db..2885aa3 100644
--- a/config/api_platform/resources.xml
+++ b/config/api_platform/resources.xml
@@ -77,6 +77,7 @@
 
     
         
+        
         
         
     
@@ -108,7 +109,6 @@
     public
     
         
-        
         
             
         
@@ -118,4 +118,19 @@
     
 
 
+
+    
+        
+        
+    
+
+
+
+    
+        
+        
+        
+    
+
+
 
\ No newline at end of file
diff --git a/migrations/Version20240129212818.php b/migrations/Version20240129212818.php
deleted file mode 100644
index da5f16d..0000000
--- a/migrations/Version20240129212818.php
+++ /dev/null
@@ -1,31 +0,0 @@
-addSql('CREATE SCHEMA public');
-    }
-}
diff --git a/migrations/Version20240219220159.php b/migrations/Version20240219220159.php
new file mode 100644
index 0000000..f3fa10f
--- /dev/null
+++ b/migrations/Version20240219220159.php
@@ -0,0 +1,112 @@
+addSql('CREATE TABLE "character" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, name VARCHAR(255) NOT NULL, strength INT NOT NULL, constitution INT NOT NULL, agility INT NOT NULL, chi INT NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE INDEX IDX_937AB03432F09E9C ON "character" (dojo_id)');
+        $this->addSql('COMMENT ON COLUMN "character".id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN "character".dojo_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE character_technique (character_id UUID NOT NULL, technique_id UUID NOT NULL, PRIMARY KEY(character_id, technique_id))');
+        $this->addSql('CREATE INDEX IDX_506B3A7A1136BE75 ON character_technique (character_id)');
+        $this->addSql('CREATE INDEX IDX_506B3A7A1F8ACB26 ON character_technique (technique_id)');
+        $this->addSql('COMMENT ON COLUMN character_technique.character_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN character_technique.technique_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE city (id UUID NOT NULL, dungeon_id UUID NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_2D5B0234B606863 ON city (dungeon_id)');
+        $this->addSql('COMMENT ON COLUMN city.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN city.dungeon_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE country (id UUID NOT NULL, capital_id UUID NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_5373C966FC2D9FF7 ON country (capital_id)');
+        $this->addSql('COMMENT ON COLUMN country.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN country.capital_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE dojo (id UUID NOT NULL, village_id UUID DEFAULT NULL, owner_id UUID NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB15E237E06 ON dojo (name)');
+        $this->addSql('CREATE INDEX IDX_9494CCB15E0D5582 ON dojo (village_id)');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_9494CCB17E3C61F9 ON dojo (owner_id)');
+        $this->addSql('COMMENT ON COLUMN dojo.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN dojo.village_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN dojo.owner_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE dungeon (id UUID NOT NULL, city_id UUID NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_3FFA1F908BAC62AF ON dungeon (city_id)');
+        $this->addSql('COMMENT ON COLUMN dungeon.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN dungeon.city_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE prefecture (id UUID NOT NULL, capital_id UUID NOT NULL, country_id UUID NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_ABE6511AFC2D9FF7 ON prefecture (capital_id)');
+        $this->addSql('CREATE INDEX IDX_ABE6511AF92F3E70 ON prefecture (country_id)');
+        $this->addSql('COMMENT ON COLUMN prefecture.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN prefecture.capital_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN prefecture.country_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE technique (id UUID NOT NULL, prerequisite_id UUID DEFAULT NULL, costs INT NOT NULL, damage VARCHAR(255) NOT NULL, energy VARCHAR(255) NOT NULL, accuracy VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_D73B9841276AF86B ON technique (prerequisite_id)');
+        $this->addSql('COMMENT ON COLUMN technique.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN technique.prerequisite_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE "user" (id UUID NOT NULL, dojo_id UUID DEFAULT NULL, auth_name VARCHAR(255) NOT NULL, properties JSON NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D64932F09E9C ON "user" (dojo_id)');
+        $this->addSql('COMMENT ON COLUMN "user".id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN "user".dojo_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('CREATE TABLE village (id UUID NOT NULL, prefecture_id UUID NOT NULL, PRIMARY KEY(id))');
+        $this->addSql('CREATE INDEX IDX_4E6C7FAA9D39C865 ON village (prefecture_id)');
+        $this->addSql('COMMENT ON COLUMN village.id IS \'(DC2Type:ulid)\'');
+        $this->addSql('COMMENT ON COLUMN village.prefecture_id IS \'(DC2Type:ulid)\'');
+        $this->addSql('ALTER TABLE "character" ADD CONSTRAINT FK_937AB03432F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1136BE75 FOREIGN KEY (character_id) REFERENCES "character" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE character_technique ADD CONSTRAINT FK_506B3A7A1F8ACB26 FOREIGN KEY (technique_id) REFERENCES technique (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE city ADD CONSTRAINT FK_2D5B0234B606863 FOREIGN KEY (dungeon_id) REFERENCES dungeon (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE country ADD CONSTRAINT FK_5373C966FC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB15E0D5582 FOREIGN KEY (village_id) REFERENCES village (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE dojo ADD CONSTRAINT FK_9494CCB17E3C61F9 FOREIGN KEY (owner_id) REFERENCES "user" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE dungeon ADD CONSTRAINT FK_3FFA1F908BAC62AF FOREIGN KEY (city_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AFC2D9FF7 FOREIGN KEY (capital_id) REFERENCES city (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE prefecture ADD CONSTRAINT FK_ABE6511AF92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE technique ADD CONSTRAINT FK_D73B9841276AF86B FOREIGN KEY (prerequisite_id) REFERENCES technique (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D64932F09E9C FOREIGN KEY (dojo_id) REFERENCES dojo (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+        $this->addSql('ALTER TABLE village ADD CONSTRAINT FK_4E6C7FAA9D39C865 FOREIGN KEY (prefecture_id) REFERENCES prefecture (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('CREATE SCHEMA public');
+        $this->addSql('ALTER TABLE "character" DROP CONSTRAINT FK_937AB03432F09E9C');
+        $this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1136BE75');
+        $this->addSql('ALTER TABLE character_technique DROP CONSTRAINT FK_506B3A7A1F8ACB26');
+        $this->addSql('ALTER TABLE city DROP CONSTRAINT FK_2D5B0234B606863');
+        $this->addSql('ALTER TABLE country DROP CONSTRAINT FK_5373C966FC2D9FF7');
+        $this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB15E0D5582');
+        $this->addSql('ALTER TABLE dojo DROP CONSTRAINT FK_9494CCB17E3C61F9');
+        $this->addSql('ALTER TABLE dungeon DROP CONSTRAINT FK_3FFA1F908BAC62AF');
+        $this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AFC2D9FF7');
+        $this->addSql('ALTER TABLE prefecture DROP CONSTRAINT FK_ABE6511AF92F3E70');
+        $this->addSql('ALTER TABLE technique DROP CONSTRAINT FK_D73B9841276AF86B');
+        $this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D64932F09E9C');
+        $this->addSql('ALTER TABLE village DROP CONSTRAINT FK_4E6C7FAA9D39C865');
+        $this->addSql('DROP TABLE "character"');
+        $this->addSql('DROP TABLE character_technique');
+        $this->addSql('DROP TABLE city');
+        $this->addSql('DROP TABLE country');
+        $this->addSql('DROP TABLE dojo');
+        $this->addSql('DROP TABLE dungeon');
+        $this->addSql('DROP TABLE prefecture');
+        $this->addSql('DROP TABLE technique');
+        $this->addSql('DROP TABLE "user"');
+        $this->addSql('DROP TABLE village');
+    }
+}
diff --git a/src/Controller/GetUserDojo.php b/src/Controller/GetUserDojo.php
new file mode 100644
index 0000000..d6607b2
--- /dev/null
+++ b/src/Controller/GetUserDojo.php
@@ -0,0 +1,21 @@
+getRepository(Dojo::class)->findOneByOwner($this->security->getUser());
+    }
+}
+
diff --git a/src/Entity/Character.php b/src/Entity/Character.php
index 58569f6..41231bd 100644
--- a/src/Entity/Character.php
+++ b/src/Entity/Character.php
@@ -1,6 +1,8 @@
 getStrength());
+        $costs += self::skillCosts($this->getConstitution());
+        $costs += self::skillCosts($this->getAgility());
+        $costs += self::skillCosts($this->getChi());
+
+        foreach ($this->getTechniques() as $tech) {
+            $costs += $tech->getCosts();
+        }
+        return $available - $costs;
     }
 
-    public function getDojo(): ?Dojo
+    public static function loadValidatorMetadata(ClassMetadata $metadata): void
     {
-        return $this->dojo;
+        $metadata->addConstraint(new CharacterStats());
     }
 
-    public function setDojo(?Dojo $dojo): static
+    /**
+     * Calculates the aged based on the ulid value?
+     */
+    #[Groups('public')]
+    public function getAge(): int
     {
-        $this->dojo = $dojo;
+        return 21;
+    }
 
-        return $this;
+    public static function skillCosts(int $value)
+    {
+        return pow(2, $value);
     }
 
     public function getName(): ?string
@@ -92,14 +118,14 @@ class Character extends Thing
         return $this;
     }
 
-    public function getConstition(): ?int
+    public function getConstitution(): ?int
     {
-        return $this->constition;
+        return $this->constitution;
     }
 
-    public function setConstition(int $constition): static
+    public function setConstitution(int $constitution): static
     {
-        $this->constition = $constition;
+        $this->constitution = $constitution;
 
         return $this;
     }
@@ -116,45 +142,48 @@ class Character extends Thing
         return $this;
     }
 
-    /**
-     * @return Collection
-     */
-    public function getTechniques(): Collection
+    public function getChi(): ?int
     {
-        return $this->techniques;
+        return $this->chi;
     }
 
-    public function setTechniques(string $techniques): static
+    public function setChi(int $chi): static
     {
-        $this->techniques = $techniques;
+        $this->chi = $chi;
 
         return $this;
     }
 
-    public function addTechnique(Technique $technique): static
+    public function getDojo(): ?Dojo
     {
-        if (!$this->techniques->contains($technique)) {
-            $this->techniques->add($technique);
-        }
-
-        return $this;
+        return $this->dojo;
     }
 
-    public function removeTechnique(Technique $technique): static
+    public function setDojo(?Dojo $dojo): static
     {
-        $this->techniques->removeElement($technique);
+        $this->dojo = $dojo;
 
         return $this;
     }
 
-    public function getConstitution(): ?int
+    /**
+     *
+     * @return Technique[]
+     */
+    public function getTechniques(): mixed
     {
-        return $this->constitution;
+        return $this->techniques->getValues();
     }
 
-    public function setConstitution(int $constitution): static
+    public function addTechnique(Technique $technique): static
     {
-        $this->constitution = $constitution;
+        $this->techniques[] = $technique;
+        return $this;
+    }
+
+    public function removeTechnique(Technique $technique): static
+    {
+        $this->techniques->removeElement($technique);
 
         return $this;
     }
diff --git a/src/Entity/Technique.php b/src/Entity/Technique.php
index b16d980..340d6b5 100644
--- a/src/Entity/Technique.php
+++ b/src/Entity/Technique.php
@@ -6,7 +6,7 @@ use Doctrine\ORM\Mapping\Entity;
 use Doctrine\ORM\Mapping\JoinColumn;
 use Doctrine\ORM\Mapping\OneToOne;
 
-#[Entity]
+#[Entity(repositoryClass: 'App\Repository\TechniqueRepository')]
 class Technique extends Thing
 {
 
@@ -17,19 +17,19 @@ class Technique extends Thing
     public int $costs;
 
     /**
-     * Forumula to calculate the damage based on the stats.
+     * Formula to calculate the damage based on the stats.
      */
     #[Column]
     public string $damage;
 
     /**
-     * Forumula to calculate the damage based on the stats.
+     * Formula to calculate the consumed energy on use based on the stats.
      */
     #[Column]
     public string $energy;
 
     /**
-     * Forumula to calculate the damage based on the stats.
+     * Formula to calculate the hit chance accuracy based on the stats.
      */
     #[Column]
     public string $accuracy;
diff --git a/src/Entity/Thing.php b/src/Entity/Thing.php
index 4d19bea..f883cdb 100644
--- a/src/Entity/Thing.php
+++ b/src/Entity/Thing.php
@@ -3,6 +3,7 @@ namespace App\Entity;
 
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Bridge\Doctrine\Types\UlidType;
+use Symfony\Component\Serializer\Attribute\Groups;
 use Symfony\Component\Uid\Ulid;
 
 abstract class Thing
@@ -12,6 +13,12 @@ abstract class Thing
     #[ORM\Column(type: UlidType::NAME, unique: true)]
     #[ORM\GeneratedValue(strategy: 'CUSTOM')]
     #[ORM\CustomIdGenerator(class: 'doctrine.ulid_generator')]
+    #[Groups('public')]
     public ?Ulid $id;
+
+    public function getId(): ?Ulid
+    {
+        return $this->id;
+    }
 }
 
diff --git a/src/Entity/User.php b/src/Entity/User.php
index e50aa35..c22d298 100644
--- a/src/Entity/User.php
+++ b/src/Entity/User.php
@@ -9,7 +9,7 @@ use Doctrine\ORM\Mapping\OneToOne;
 use Doctrine\ORM\Mapping\Table;
 use Symfony\Component\Security\Core\User\UserInterface;
 
-#[Entity(repositoryClass: "App\Repository\UserRepository")]
+#[Entity(repositoryClass: 'App\Repository\UserRepository')]
 #[Table(name: '`user`')]
 class User extends Thing implements UserInterface
 {
diff --git a/src/Factory/CharacterFactory.php b/src/Factory/CharacterFactory.php
index bf9cdbb..0b61aae 100644
--- a/src/Factory/CharacterFactory.php
+++ b/src/Factory/CharacterFactory.php
@@ -47,10 +47,11 @@ final class CharacterFactory extends ModelFactory
     protected function getDefaults(): array
     {
         return [
-            'name' => self::faker()->text(),
+            'name' => self::faker()->firstName(),
             'strength' => self::faker()->numberBetween(1, 4),
             'constitution' => self::faker()->numberBetween(1, 4),
             'agility' => self::faker()->numberBetween(1, 4),
+            'chi' => self::faker()->numberBetween(1, 4),
             'techniques' => TechniqueFactory::createMany(2)
         ];
     }
diff --git a/src/Repository/TechniqueRepository.php b/src/Repository/TechniqueRepository.php
new file mode 100644
index 0000000..d8a97c3
--- /dev/null
+++ b/src/Repository/TechniqueRepository.php
@@ -0,0 +1,24 @@
+
+ *
+ * @method Technique|null find($id, $lockMode = null, $lockVersion = null)
+ * @method Technique|null findOneBy(array $criteria, array $orderBy = null)
+ * @method Technique[] findAll()
+ * @method Technique[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
+ */
+class TechniqueRepository extends ServiceEntityRepository
+{
+
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, Technique::class);
+    }
+}
diff --git a/src/Validator/CharacterStats.php b/src/Validator/CharacterStats.php
new file mode 100644
index 0000000..bc1cee6
--- /dev/null
+++ b/src/Validator/CharacterStats.php
@@ -0,0 +1,16 @@
+getFreeSkillPoints() < 0) {
+            $this->context->buildViolation($constraint->noMoreSkillPointsMessage)
+                ->atPath('character.freeSkillPoints')
+                ->addViolation();
+        }
+    }
+}
+
diff --git a/tests/AbstractTest.php b/tests/AbstractTest.php
new file mode 100644
index 0000000..f110a1f
--- /dev/null
+++ b/tests/AbstractTest.php
@@ -0,0 +1,42 @@
+format("c");
+
+        return sodium_bin2base64(sodium_crypto_sign($message, $sign_secret), SODIUM_BASE64_VARIANT_URLSAFE);
+    }
+
+    protected static function createClientWithToken($authName = null): Client
+    {
+        return static::createClient([],
+            [
+                'headers' => [
+                    'accept' => 'application/json',
+                    'X-AUTH-TOKEN' => static::generateAuthToken($authName)
+                ]
+            ]);
+    }
+}
+
diff --git a/tests/CharacterTest.php b/tests/CharacterTest.php
index 627202a..c3fa502 100644
--- a/tests/CharacterTest.php
+++ b/tests/CharacterTest.php
@@ -1,28 +1,13 @@
 format("c");
-
-        return sodium_bin2base64(sodium_crypto_sign($message, $sign_secret), SODIUM_BASE64_VARIANT_URLSAFE);
-    }
 
     /**
      * Requirement: A user should be able see all characters from a dojo, but only the public fields!
@@ -36,65 +21,173 @@ class CharacterTest extends ApiTestCase
         ]);
         CharacterFactory::createMany(10);
 
-        $response = static::createClient()->request('GET', '/api/dojo/' . $dojo->id . '/characters',
-            [
-                'headers' => [
-                    'accept' => 'application/json',
-                    'X-AUTH-TOKEN' => $this->generateAuthToken($requestUser->authName)
-                ]
-            ]);
+        $response = static::createClientWithToken($requestUser->authName)->request('GET',
+            '/api/dojo/' . $dojo->id . '/characters');
 
         $this->assertResponseStatusCodeSame(200);
 
+        $this->assertNotEquals("[[],[],[],[]]", $response->getContent());
+
         // Because test fixtures are automatically loaded between each test, you can assert on them
         $this->assertCount(4, $response->toArray());
 
-        $this->assertNotEquals("[[],[],[],[]]", $response->getContent());
-
         $chars = $response->toArray();
+        $this->assertEquals(4, count($chars[0]));
+        $this->assertArrayHasKey('id', $chars[0]);
         $this->assertArrayHasKey('name', $chars[0]);
-        $this->assertArrayHasKey('dojo', $chars[0]);
+        $this->assertEquals('/api/dojos/' . $dojo->getId()
+            ->toBase32(), $chars[0]['dojo']);
+        $this->assertArrayHasKey('age', $chars[0]);
+        $this->assertArrayNotHasKey('freeSkillPoints', $chars[0]);
         $this->assertArrayNotHasKey('strength', $chars[0]); // not accessible via this route
         $this->assertArrayNotHasKey('constitution', $chars[0]); // not accessible via this route
         $this->assertArrayNotHasKey('agility', $chars[0]); // not accessible via this route
+        $this->assertArrayNotHasKey('chi', $chars[0]); // not accessible via this route
         $this->assertArrayNotHasKey('techniques', $chars[0]); // not accessible via this route
     }
 
     /**
-     * Requirement: A user should be able see all characters from a dojo, but only the public fields!
+     * Requirement: A user should be able see all of the characters from his dojo, not restricted by public fields!
      */
     public function testRetrieveCharactersFromOwnDojoDetail(): void
     {
         $dojo = DojoFactory::createOne([
             'owner' => UserFactory::createOne()
         ]);
-        CharacterFactory::createMany(4, [
-            'dojo' => $dojo
+
+        $technique = TechniqueFactory::createOne();
+
+        $foo = CharacterFactory::createMany(4, [
+            'dojo' => $dojo,
+            'techniques' => [
+                $technique
+            ]
         ]);
+
+        $this->assertEquals(1, count($foo[0]->getTechniques()));
+
         CharacterFactory::createMany(10);
 
-        $response = static::createClient()->request('GET', '/api/dojo/characters',
-            [
-                'headers' => [
-                    'accept' => 'application/json',
-                    'X-AUTH-TOKEN' => $this->generateAuthToken($dojo->getOwner()->authName)
-                ]
-            ]);
+        $response = static::createClientWithToken($dojo->getOwner()->authName)->request('GET', '/api/dojo/characters');
 
         $this->assertResponseStatusCodeSame(200);
 
-        // Because test fixtures are automatically loaded between each test, you can assert on them
-        $this->assertCount(4, $response->toArray());
-
         $this->assertNotEquals("[[],[],[],[]]", $response->getContent());
 
         $chars = $response->toArray();
+        $this->assertEquals(10, count($chars[0]));
+        $this->assertArrayHasKey('id', $chars[0]);
         $this->assertArrayHasKey('name', $chars[0]);
         $this->assertArrayHasKey('dojo', $chars[0]);
-        $this->assertArrayHasKey('strength', $chars[0]); // not accessible via this route
-        $this->assertArrayHasKey('constitution', $chars[0]); // not accessible via this route
-        $this->assertArrayHasKey('agility', $chars[0]); // not accessible via this route
-        $this->assertArrayHasKey('techniques', $chars[0]); // not accessible via this route
+        $this->assertEquals('/api/dojos/' . $dojo->getId()
+            ->toBase32(), $chars[0]['dojo']);
+        $this->assertArrayHasKey('age', $chars[0]);
+        $this->assertArrayHasKey('freeSkillPoints', $chars[0]);
+        $this->assertArrayHasKey('strength', $chars[0]);
+        $this->assertArrayHasKey('constitution', $chars[0]);
+        $this->assertArrayHasKey('agility', $chars[0]);
+        $this->assertArrayHasKey('chi', $chars[0]);
+        $this->assertArrayHasKey('techniques', $chars[0]);
+        $this->assertEquals('/api/techniques/' . $technique->getId()
+            ->toBase32(), $chars[0]['techniques'][0]);
+    }
+
+    /**
+     * Requirement: MVP only (in the future the recuitment will be different).
+     * A user should be able to create a single character.
+     */
+    public function testCreateCharacter(): void
+    {
+        $dojo = DojoFactory::createOne([
+            'owner' => UserFactory::createOne()
+        ]);
+
+        $tech = TechniqueFactory::createOne([
+            'prerequisite' => NULL
+        ]);
+
+        $response = static::createClientWithToken($dojo->getOwner()->authName)->request('POST', '/api/characters',
+            [
+                'json' => [
+                    'name' => 'Dude',
+                    'strength' => 1,
+                    'constitution' => 1,
+                    'agility' => 1,
+                    'chi' => 1,
+                    'techniques' => [
+                        '/api/techniques/' . $tech->getId()
+                            ->toBase32()
+                    ]
+                ]
+            ]);
+
+        $this->assertResponseStatusCodeSame(201);
+
+        $this->assertArrayHasKey('id', $response->toArray());
+    }
+
+    /**
+     * Requirement: MVP only (in the future the recuitment will be different).
+     * A user should NOT be able spent more skill points than available.
+     */
+    public function testCreateCharacterStatsTooHigh(): void
+    {
+        $dojo = DojoFactory::createOne([
+            'owner' => UserFactory::createOne()
+        ]);
+
+        $tech = TechniqueFactory::createOne([
+            'prerequisite' => NULL
+        ]);
+
+        static::createClientWithToken($dojo->getOwner()->authName)->request('POST', '/api/characters',
+            [
+                'json' => [
+                    'name' => 'Dude',
+                    'strength' => 99,
+                    'constitution' => 1,
+                    'agility' => 1,
+                    'chi' => 1,
+                    'techniques' => [
+                        '/api/techniques/' . $tech->getId()
+                            ->toBase32()
+                    ]
+                ]
+            ]);
+
+        $this->assertResponseStatusCodeSame(422);
+    }
+
+    /**
+     * Requirement: MVP only (in the future the recuitment will be different).
+     * A user should NOT be able spent more skill points than available.
+     */
+    public function testCreateCharacterTooExpensiveTechnique(): void
+    {
+        $dojo = DojoFactory::createOne([
+            'owner' => UserFactory::createOne()
+        ]);
+
+        $tech = TechniqueFactory::createOne([
+            'costs' => 99
+        ]);
+
+        static::createClientWithToken($dojo->getOwner()->authName)->request('POST', '/api/characters',
+            [
+                'json' => [
+                    'name' => 'Dude',
+                    'strength' => 1,
+                    'constitution' => 1,
+                    'agility' => 1,
+                    'chi' => 1,
+                    'techniques' => [
+                        '/api/techniques/' . $tech->getId()
+                            ->toBase32()
+                    ]
+                ]
+            ]);
+
+        $this->assertResponseStatusCodeSame(422);
     }
 }
 
diff --git a/tests/DojoTest.php b/tests/DojoTest.php
index 0975c82..8d0520c 100644
--- a/tests/DojoTest.php
+++ b/tests/DojoTest.php
@@ -1,30 +1,12 @@
 format("c");
-
-        return sodium_bin2base64(sodium_crypto_sign($message, $sign_secret), SODIUM_BASE64_VARIANT_URLSAFE);
-    }
 
     /**
      * Requirement: A user should be able to create a dojo!
@@ -37,22 +19,63 @@ class DojoTest extends ApiTestCase
 
         $this->assertCount(0, $userRepository->findByAuthName($userName));
 
-        static::createClient()->request('POST', '/api/dojos',
-            [
-                'headers' => [
-                    'accept' => 'application/json',
-                    'X-AUTH-TOKEN' => $this->generateAuthToken($userName)
-                ],
-                'json' => [
-                    'name' => $dojoName
-                ]
-            ]);
+        static::createClientWithToken($userName)->request('POST', '/api/dojos', [
+            'json' => [
+                'name' => $dojoName
+            ]
+        ]);
 
         $this->assertResponseStatusCodeSame(201);
 
         $this->assertCount(1, $userRepository->findByAuthName($userName));
     }
 
+    /**
+     * Requirement: A user should be request his own dojo!
+     */
+    public function testUserReadDojo(): void
+    {
+        $userName = "FooBarFigher";
+        $dojoName = "BigFightDojo";
+        $dojo = DojoFactory::createOne(
+            [
+                'name' => $dojoName,
+                'owner' => UserFactory::createOne([
+                    'authName' => $userName
+                ])
+            ]);
+
+        static::createClientWithToken($userName)->request('GET', '/api/dojo');
+
+        $this->assertResponseStatusCodeSame(200);
+
+        $this->assertJsonContains(
+            [
+                'name' => 'BigFightDojo',
+                'members' => [],
+                'owner' => '/api/users/' . $dojo->owner->getId()
+                    ->toBase32(),
+                'id' => $dojo->getId()
+                    ->toBase32()
+            ]);
+    }
+
+    /**
+     * Requirement: A user should be request his own dojo!
+     * Fails, if the dojo is not yet created.
+     */
+    public function testUserReadDojoNotYetCreated(): void
+    {
+        $userName = "FooBarFigher";
+        $userRepository = $this->getContainer()->get(UserRepository::class);
+
+        $this->assertCount(0, $userRepository->findByAuthName($userName));
+
+        static::createClientWithToken($userName)->request('GET', '/api/dojo');
+
+        $this->assertResponseStatusCodeSame(404);
+    }
+
     /**
      * Requirement: A user should NOT be able to create more than one dojos!
      */
@@ -67,16 +90,11 @@ class DojoTest extends ApiTestCase
             ])
         ]);
 
-        static::createClient()->request('POST', '/api/dojos',
-            [
-                'headers' => [
-                    'accept' => 'application/json',
-                    'X-AUTH-TOKEN' => $this->generateAuthToken($userName)
-                ],
-                'json' => [
-                    'name' => $dojoName
-                ]
-            ]);
+        static::createClientWithToken($userName)->request('POST', '/api/dojos', [
+            'json' => [
+                'name' => $dojoName
+            ]
+        ]);
 
         $this->assertResponseStatusCodeSame(409); // 409 Conflict
     }
@@ -98,12 +116,10 @@ class DojoTest extends ApiTestCase
                 ])
             ]);
 
-        static::createClient()->request('PATCH', '/api/dojos/' . $dojo->id,
+        static::createClientWithToken($userName)->request('PATCH', '/api/dojos/' . $dojo->id,
             [
                 'headers' => [
-                    'content-type' => 'application/merge-patch+json',
-                    'accept' => 'application/json',
-                    'X-AUTH-TOKEN' => $this->generateAuthToken($userName)
+                    'content-type' => 'application/merge-patch+json'
                 ],
                 'json' => [
                     'name' => $newDojoName