How can you programmatically create a user in a Cognito User Pool?

Here is an example using python/Flask

import traceback
import boto3
from flask import Flask, render_template, request

app = Flask(__name__)


def cognito_register_user(email):
    print("sign up user: ", email)

    try:
        aws_client = boto3.client('cognito-idp', region_name = "us-west-2",)
        response = aws_client.admin_create_user(UserPoolId="us-west-2_sdfgsdfgsdfg",Username=email,UserAttributes=[{"Name": "email","Value": email},{ "Name": "email_verified", "Value": "true" }],DesiredDeliveryMediums=['EMAIL'])
        print("response=", response)
        return response
    except:
        traceback.print_exc()
    return None


@app.route('/')
def root():
    return render_template('register_email.html', title='register mail')


@app.route('/register/email', methods=['POST'])
def sign_up():
    if request.method == 'POST':
        email = request.form['email']
        print("email=", email)
        cognito_register_user(email)
    return render_template('register_email_complete.html', title='flask test', email=email)


if __name__ == "__main__":
    app.run(debug=True)

It's actually quite easy if you follow the development documentation (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html), more specifically the "signUp" function.

From the Docs:

var params = {
  ClientId: 'STRING_VALUE', /* required */
  Password: 'STRING_VALUE', /* required */
  Username: 'STRING_VALUE', /* required */
  AnalyticsMetadata: {
    AnalyticsEndpointId: 'STRING_VALUE'
  },
  SecretHash: 'STRING_VALUE',
  UserAttributes: [
    {
      Name: 'STRING_VALUE', /* required */
      Value: 'STRING_VALUE'
    },
    /* more items */
  ],
  UserContextData: {
    EncodedData: 'STRING_VALUE'
  },
  ValidationData: [
    {
      Name: 'STRING_VALUE', /* required */
      Value: 'STRING_VALUE'
    },
    /* more items */
  ]
};
cognitoidentityserviceprovider.signUp(params, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

And using this, it's simple to create a user (example in Lambda, but can easily be modified as JS on its own):

'use strict'
var AWS = require('aws-sdk');
var resp200ok = { statusCode: 200, headers: {'Content-Type': 'application/json'}, body: {} };
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
// ^ Hard to find that this is the way to import the library, but it was obvious in docs

exports.handler = function(event, context, callback){
    var params = {
        ClientId: 'the App Client you set up with your identity pool (usually 26 alphanum chars)',
        Password: 'the password you want the user to have (keep in mind the password restrictions you set when creating pool)',
        Username: 'the username you want the user to have',
        UserAttributes:[ {
            {
                Name: 'name', 
                Value: 'Private'
            }, 
            {
                Name: 'family_name', 
                Value: 'Not-Tellinglol'
            },
        }],
    };

    cognitoidentityserviceprovider.signUp(params, function(err, data) {
        if (err){ console.log(err, err.stack); }
        else{ resp200ok.body = JSON.stringify(data); callback(null, resp200ok); }
    });
};

Anything you set to required in your Cognito pool setup has to be in the UserAttributes section (usually the email is defaulted to required, check if yours is). The list of things you can assign values to is found in (Cognito pool) General Settings -> App Clients -> Show Details -> Set Read/Write -> (list of things), here you can add custom attributes (like if you want to specify what city your user is from, or if you want to add whatever else (String/Number)).

When assigning a value to a custom field, your "Name" in the UserAttributes will be "custom:whatever", so if the custom field is "city" the Name is "custom:city".

Hopefully I wasn't stating too much of the obvious, but these are things it took me a while to figure out with the broken up SO info, and AWS docs, and I figured I'd plop it all together.