I believe I know how to do this now. I would be grateful for anyone to weigh in on the "right" way to do this, because this process seems a little weird.
Using the UI, you can create a web using a stock template within a site collection and customize it by adding pieces to it, and removing things which you don't want. Then, with the web selected that you wish to use as a template, as admin, choose 'Site Settings' and then 'Save Site as Template' where you can then assign a filename, friendly name, and descriptive text. Doing this places the resulting template into the database evidently and creates a reference which lives in the 'Solutions' list also on the Site Settings page. (If you visit the 'Solutions' list you can click on the template and save it as a local file which can then be uploaded to another site, which is helpful).
It's reasonably well-known that you can create a site in code by adding a new web to a site's web collection, which looks like this:
SPWeb newWeb = subSite.Webs.Add(
"pathtoweb",
"Title of New Web",
"Web Description",
1033,
template,
false, false);
where 'template' here is an instance of the SPWebTemplate you want to use. If it's one of the stock templates, you can usually refer to them by name e.g., "STS#0" and so on instead of the template reference shown here. The question is: how to get the name of the customized template to use it in the API call.
To find the 'name' of the template that was created, I used PowerShell like this
$x = get-spsite http://machine/managedpath/sitecollectionname
$x.GetWebTemplates(1033)
which dumped all the templates on this subsite, and included my modified templates at the end with not very convenient names which I copied and pasted in to my C# program.
I didn't explore all the permutations here, e.g., you can probably just use the GUID-based name in the .Add call, but to be explicit, this is the sequence that worked for me. I would love to hear that this is madness-- please let me know something more elegant:
// or any of the other hundred ways to do this...
SPSite s = new SPSite("your url here");
SPWeb subSite = s.RootWeb;
// 1033 is the locale id for English
SPWebTemplateCollection wtc = s.GetWebTemplates(1033);
// use the name for the index
SPWebTemplate template =
wtc["{8925048C-DF71-guidguidguidguid}#MyTemplate"];
SPWeb newWeb = subSite.Webs.Add(
"pathtoweb",
"Title of New Web",
"Web Description",
1033,
template,
false, false);
SharePoint!