Problem with unmasking a database user during a sproc
To be honest, I've never used SQL Server masking before so this is mostly a guess, but if you try to run just the line of code EXEC('GRANT UNMASK TO apiuser'); directly, does it work?
I'm thinking by executing dynamic SQL you're running into the same limitation as if you created a temp table with dynamic SQL and then tried to access that table outside of the dynamic SQL after (it's not possible).
I can't find exactly why that's how SQL Server works with dynamic SQL, but here's some relevant posts (regarding temp tables) and I bet you're experiencing the same thing with unmask:
SQL Authority: SQL Server Dynamic SQL and Temporary Tables
StackOverflow: T-SQL Dynamic SQL and Temp Tables
As a solution, can you run just the GRANT UNMASK directly (eliminate the dynamic SQL) after the IF instead like your first example?
if exists (select name from [sys].[database_principals] where name=N'apiuser')
GRANT UNMASK TO apiuser;