bpy.ops.render.render does not find camera
Simply set the scene.camera after you add the camera.

from bpy import context
scene = context.scene

...

bpy.ops.object.camera_add(location=(0, 4, 4), 
                          rotation=(-0.7853, 0, 0))
scene.camera = context.object
...


Hitting F12 invokes the operator, which  when scene.camera is None , throws a message if no cam, or uses a camera from the scene and sets it to scene.camera.  Test by adding a few cameras, setting scene.camera to None, and pressing F12.

To invoke the operator from code,

bpy.ops.render.render('INVOKE_DEFAULT', write_still=True)


Note: bpy.data contains all the objects in the blend file. context.scene.objects contains all the objects in the context scene.  The context scene may not necessarily be bpy.data.scenes["Scene"]. render.render renders the context scene, unless another scene is specified.

A tip, set up a context variable, either context = bpy.context or from bpy import context at the beginning of your test code, then later cut and paste into, for instance, operator execute(self, context) methods. Setting vars like  scene = context.scene, obj = context.object, obj.scale = (0.1, 1, 10) makes code far more readable IMO rather than always addressing from bpy.