Smarty only generating nulls from API calls
So, for posterity's sake, I wanted to share the answer I figured out.

When I looked at the Source view of the email in CiviCRM, I realized that the code had pasted as


&lt;p&gt;id:&amp;nbsp;{contact.contact_id}&lt;/p&gt;

&lt;p&gt;smarty id: {$contact_id}&lt;/p&gt;

&lt;p&gt;{crmAPI var=&amp;#39;result&amp;#39; entity=&amp;#39;Contact&amp;#39; action=&amp;#39;get&amp;#39; id=203}&lt;/p&gt;

&lt;p&gt;{$result|@debug_print_var}&lt;/p&gt;



instead of 

{capture assign=contact_id}{contact.contact_id}{/capture}

id: {contact.contact_id}

smarty id: {$contact_id}

{crmAPI var='result' entity='Contact' action='get' id=203}

{$result|@debug_print_var}


When I composed the code correctly in the Source view rather than the HTML view, everything worked as expected!