Gustavo Manduca scored one and created the 75th-minute winner for Ailton as the hosts recovered from conceding to Konstatin Zyryanov against the run of play.
Zenit were dealt another setback when Bruno Alves was sent off for a second yellow card with 14 minutes to go, but they piled on late pressure and might have snatched a point had Viktor Fayzulin's shot gone in rather than hit the bar.
The hosts were the first to threaten when Zenit goalkeeper Vyacheslav Malafeev was forced to punch clear Marcinho's cross.
Malafeev then parried Ailton's shot from 12 yards as another of Apoel's Brazilian contingent tried his luck.
The Russian stopper was keeping his side on level terms and denied Ivan Trickovski minutes later.
Zenit finally got going, though, and Nicolas Lombaerts headed Roman Shirokov's left-wing cross wide at the far post.
But that was a rare moment of adventure for the visitors and Trickovski drilled an effort wide from the edge of the area at the other end.
The Cypriots continued to dominate after the break and the lively Trickovski had another shot parried by the over-worked Malafeev.
Marcinho then fired over the top from long range before Ailton headed over from a Trickovski ball in.
But Zenit went in front completely against the run of play in the 63rd minute.
Danny played the ball in from the right and Zyryanov guided a low finish into the bottom right corner.
Suddenly Zenit were the side making all the running, Alexander Kerzhakov twice mis-hitting shots wide in quick succession and Danny having an effort blocked by defender Paulo Jorge.
But within the space of three minutes Apoel had turned the game on its head.
Manduca volleyed home a 73rd-minute equaliser from the left of the area before setting up Ailton to curl a second low inside the far post from 18 yards.
And things went from bad to worse for Zenit a minute later when Alves fouled Ailton and was shown a second yellow card.
The Russians poured forward in search of an equaliser in the closing stages with Danny seeing a shot saved by Dionisis Chiotis and Viktor Fayzulin crashing a shot against the bar.
Fayzulin then crossed for Lombaerts who headed wide as Apoel held on for an important win.