Matt Connolly was wrongly penalised for handball by referee David Coote just before the break as Birmingham moved to within a point of the Sky Bet Championship top six.
It ended a four-game winless streak at St Andrew's and lifted them above the Bluebirds to seventh.
Defeat was harsh on Cardiff who dominated most of the second half, and went close through Sammy Ameobi, but they paid the price for wasteful finishing and woeful refereeing.
It had shaped up to be an instantly forgettable first half which saw Neal Eardley - who was replaced by Caddis - and Sean Morrison limp off injured for either side.
Anthony Pilkington's drive deflected over while Tomasz Kuszczak easily saved Ameobi's weak effort five minutes before the break.
Birmingham offered nothing going forward and Huddersfield loanee James Vaughan was left to feed off scraps.
Cardiff had not lost against their hosts since 2008, a record which rarely looked under threat before penalty drama in first half stoppage time.
David Marshall dropped Jon Toral's free kick under pressure and Connolly threw himself in front of Vaughan's shot to block the ball with his face.
Bizarrely referee Coote gave the penalty - to Cardiff's fury - and Caddis sent Marshall the wrong way from the spot.
Bluebirds boss Russell Slade was stopped from confronting the official in the tunnel at the break and he emerged to see his side almost fall further behind on 49 minutes.
Maikel Kieftenbeld robbed dithering Cardiff to find Jacques Maghoma and he fed Toral, who was denied by Marshall at the near post.
But the visitors dominated from then and nearly levelled on 65 minutes when Pilkington flashed an effort across goal.
And Ameobi wasted a golden chance to level five minutes later when, put in by Tony Watt, he fired wide from eight yards.
Jonathan Spector then turned Watt's cross onto his own post as the visitors got closer before Charlton loanee Watt lashed wide.
Marshall parried Demarai Gray's fierce drive as Birmingham almost wrapped up victory but Kuszczak ensured the points when he turned Scott Malone's last-minute effort wide.