Working with Prims (BasisCurves)

I’ve recently started working with extensions in USD Composer and am attempting to make a piece of code that will create a curve from a series of XYZ points. I’ve scoured for videos and documentation on how to achieve certain things, but some things still evade me.
I’ve been following the echoed info in the command window for some things, but when it comes to creating curves it spits out point by point:

omni.kit.commands.execute('Group')

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.type'),
	value='cubic',
	prev=None)

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.curveVertexCounts'),
	value=Vt.IntArray(1, (2,)),
	prev=[])

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.points'),
	value=Vt.Vec3fArray(2, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375))),
	prev=[])

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.extent'),
	value=Vt.Vec3fArray(2, (Gf.Vec3f(53.208251953125, -12.5, -230.56878662109375), Gf.Vec3f(78.208251953125, 12.5, -205.56878662109375))),
	prev=None)

omni.kit.commands.execute('Group')

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.curveVertexCounts'),
	value=Vt.IntArray(1, (4,)),
	prev=Vt.IntArray(1, (2,)))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.points'),
	value=Vt.Vec3fArray(4, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562))),
	prev=Vt.Vec3fArray(2, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375))))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.extent'),
	value=Vt.Vec3fArray(2, (Gf.Vec3f(53.208251953125, -12.500030517578125, -230.56878662109375), Gf.Vec3f(161.75588989257812, 12.5, 114.18399047851562))),
	prev=None)

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.widths'),
	value=Vt.FloatArray(4, (25, 25, 25, 25)),
	prev=Vt.FloatArray(1, (25,)))

omni.kit.commands.execute('Group')

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.curveVertexCounts'),
	value=Vt.IntArray(1, (7,)),
	prev=Vt.IntArray(1, (4,)))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.points'),
	value=Vt.Vec3fArray(7, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375))),
	prev=Vt.Vec3fArray(4, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562))))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.extent'),
	value=Vt.Vec3fArray(2, (Gf.Vec3f(-204.47760009765625, -12.500030517578125, -230.56878662109375), Gf.Vec3f(161.75588989257812, 12.5, 114.18399047851562))),
	prev=None)

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.widths'),
	value=Vt.FloatArray(7, (25, 25, 25, 25, 25, 25, 25)),
	prev=Vt.FloatArray(4, (25, 25, 25, 25)))

omni.kit.commands.execute('Group')

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.curveVertexCounts'),
	value=Vt.IntArray(1, (10,)),
	prev=Vt.IntArray(1, (7,)))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.points'),
	value=Vt.Vec3fArray(10, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375), Gf.Vec3f(-236.87338256835938, 0.0, 257.6490173339844), Gf.Vec3f(-236.87338256835938, 0.0, 257.6490173339844))),
	prev=Vt.Vec3fArray(7, (Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(65.708251953125, 0.0, -218.06878662109375), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(149.25588989257812, -3.0517578125e-05, 101.68399047851562), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375), Gf.Vec3f(-191.97760009765625, 0.0, 23.90814208984375))))

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.extent'),
	value=Vt.Vec3fArray(2, (Gf.Vec3f(-249.37338256835938, -12.500030517578125, -230.56878662109375), Gf.Vec3f(161.75588989257812, 12.5, 270.1490173339844))),
	prev=None)

omni.kit.commands.execute('ChangeProperty',
	prop_path=Sdf.Path('/World/BasisCurves_01.widths'),
	value=Vt.FloatArray(10, (25, 25, 25, 25, 25, 25, 25, 25, 25, 25)),
	prev=Vt.FloatArray(7, (25, 25, 25, 25, 25, 25, 25)))

etc.

I am hoping there is a better way than looping through this format and adding each of my points individually. So I have a series of questions:

  1. Is there documentation for the API that is not UI-based? Is there a way to run from VSCode in debug mode, while I am connected to the app?
  2. When I create my curve, I can have it selected. Is there a way to manipulate ‘selected’ prims rather than have to specify a ‘path_to’? For example, editing the points / renaming.
  3. What is best practice here for adding a series of points to define a curve? Can I do it on curve creation, or do I edit it afterwards?

Maybe this helps, you can set curves with an array

import numpy as np
import omni

def create_curve(nodes, prim_path="/World/Path"):
    stage = omni.usd.get_context().get_stage()
    prim = UsdGeom.BasisCurves.Define(stage, prim_path)
    prim.CreatePointsAttr(nodes)

    # Set the number of curve verts to be the same as the number of points we have
    curve_verts = prim.CreateCurveVertexCountsAttr()
    curve_verts.Set([len(nodes)])

    # Set the curve type to linear so that each node is connected to the next
    type_attr = prim.CreateTypeAttr()
    type_attr.Set('linear')
    type_attr = prim.GetTypeAttr().Get()

    # color_primvar = prim.CreateDisplayColorPrimvar(UsdGeom.Tokens.constant)
    UsdGeom.Primvar(prim.GetDisplayColorAttr()).SetInterpolation("constant")
    prim.GetDisplayColorAttr().Set([(0, 1, 0)])
    
    
x = np.arange(0, 15, dtype=float)
y = np.arange(0, 15, dtype=float)
z = np.arange(0, 15, dtype=float)

points = np.vstack([x,y,z])

create_curve(points)