diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index f1edd293bd754f1db5c1f7eb4d448509896ad0bb..91039b9345c883aa9b80f479ac56cf177c138324 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -19,6 +19,7 @@
 #include "MHexahedron.h"
 #include "MPrism.h"
 #include "MPyramid.h"
+#include "ExtrudeParams.h"
 
 // gmsh
 
@@ -467,3 +468,163 @@ int gmshModelAddEmbedded(int dim, const std::vector<int> &tags, int toDim, int t
 }
 
 // gmshModelGeo
+
+int gmshModelGeoAddVertex(int &tag, double x, double y, double z, double lc)
+{
+  return !GModel::current()->getGEOInternals()->addVertex(tag, x, y, z, lc);
+}
+
+int gmshModelGeoAddLine(int &tag, int startTag, int endTag)
+{
+  return !GModel::current()->getGEOInternals()->addLine(tag, startTag, endTag);
+}
+
+int gmshModelGeoAddCircleArc(int &tag, int startTag, int centerTag, int endTag,
+                             double nx, double ny, double nz)
+{
+  return !GModel::current()->getGEOInternals()->addCircleArc
+    (tag, startTag, centerTag, endTag, nx, ny, nz);
+}
+
+int gmshModelGeoAddEllipseArc(int &tag, int startTag, int centerTag, int majorTag,
+                              int endTag, double nx, double ny, double nz)
+{
+  return !GModel::current()->getGEOInternals()->addEllipseArc
+    (tag, startTag, centerTag, majorTag, endTag, nx, ny, nz);
+}
+
+int gmshModelGeoAddSpline(int &tag, const std::vector<int> &vertexTags)
+{
+  return !GModel::current()->getGEOInternals()->addSpline(tag, vertexTags);
+}
+
+int gmshModelGeoAddBSpline(int &tag, const std::vector<int> &vertexTags)
+{
+  return !GModel::current()->getGEOInternals()->addBSpline(tag, vertexTags);
+}
+
+int gmshModelGeoAddBezier(int &tag, const std::vector<int> &vertexTags)
+{
+  return !GModel::current()->getGEOInternals()->addBezier(tag, vertexTags);
+}
+
+int gmshModelGeoAddLineLoop(int &tag, const std::vector<int> &edgeTags)
+{
+  return !GModel::current()->getGEOInternals()->addLineLoop(tag, edgeTags);
+}
+
+int gmshModelGeoAddPlaneSurface(int &tag, const std::vector<int> &wireTags)
+{
+  return !GModel::current()->getGEOInternals()->addPlaneSurface(tag, wireTags);
+}
+
+int gmshModelGeoAddSurfaceFilling(int &tag, const std::vector<int> &wireTags,
+                                  int sphereCenterTag)
+{
+  return !GModel::current()->getGEOInternals()->addSurfaceFilling
+    (tag, wireTags, sphereCenterTag);
+}
+
+int gmshModelGeoAddSurfaceLoop(int &tag, const std::vector<int> &faceTags)
+{
+  return !GModel::current()->getGEOInternals()->addSurfaceLoop(tag, faceTags);
+}
+
+int gmshModelGeoAddVolume(int &tag, const std::vector<int> &shellTags)
+{
+  return !GModel::current()->getGEOInternals()->addVolume(tag, shellTags);
+}
+
+static ExtrudeParams *getExtrudeParams(const std::vector<int> &numElements,
+                                       const std::vector<double> &heights,
+                                       bool recombine)
+{
+  ExtrudeParams *e = 0;
+  if(numElements.size()){
+    e = new ExtrudeParams();
+    e->mesh.ExtrudeMesh = true;
+    e->mesh.NbElmLayer = numElements;
+    e->mesh.hLayer = heights;
+    if(e->mesh.hLayer.empty()) e->mesh.hLayer.push_back(1.);
+    e->mesh.Recombine = recombine;
+  }
+  return e;
+}
+
+int gmshModelGeoExtrude(const std::vector<std::pair<int, int> > &inDimTags,
+                        double dx, double dy, double dz,
+                        std::vector<std::pair<int, int> > &outDimTags,
+                        const std::vector<int> &numElements,
+                        const std::vector<double> &heights, bool recombine)
+{
+  return !GModel::current()->getGEOInternals()->extrude
+    (inDimTags, dx, dy, dz, outDimTags,
+     getExtrudeParams(numElements, heights, recombine));
+}
+
+int gmshModelGeoRevolve(const std::vector<std::pair<int, int> > &inDimTags,
+                        double x, double y, double z,
+                        double ax, double ay, double az, double angle,
+                        std::vector<std::pair<int, int> > &outDimTags,
+                        const std::vector<int> &numElements,
+                        const std::vector<double> &heights, bool recombine)
+{
+  return !GModel::current()->getGEOInternals()->revolve
+    (inDimTags, x, y, z, ax, ay, az, angle, outDimTags,
+     getExtrudeParams(numElements, heights, recombine));
+}
+
+int gmshModelGeoTwist(const std::vector<std::pair<int, int> > &inDimTags,
+                      double x, double y, double z,
+                      double dx, double dy, double dz,
+                      double ax, double ay, double az, double angle,
+                      std::vector<std::pair<int, int> > &outDimTags,
+                      const std::vector<int> &numElements,
+                      const std::vector<double> &heights, bool recombine)
+{
+  return !GModel::current()->getGEOInternals()->twist
+    (inDimTags, x, y, z, dx, dy, dz, ax, ay, az, angle, outDimTags,
+     getExtrudeParams(numElements, heights, recombine));
+}
+
+int gmshModelGeoTranslate(const std::vector<std::pair<int, int> > &dimTags,
+                          double dx, double dy, double dz)
+{
+}
+
+int gmshModelGeoRotate(const std::vector<std::pair<int, int> > &dimTags,
+                       double x, double y, double z, double ax, double ay, double az,
+                       double angle)
+{
+}
+
+int gmshModelGeoDilate(const std::vector<std::pair<int, int> > &dimTags,
+                       double x, double y, double z,
+                       double a, double b, double c)
+{
+}
+
+int gmshModelGeoSymmetry(const std::vector<std::pair<int, int> > &dimTags,
+                         double a, double b, double c, double d)
+{
+}
+
+int gmshModelGeoCopy(const std::vector<std::pair<int, int> > &inDimTags,
+                     std::vector<std::pair<int, int> > &outDimTags)
+{
+}
+
+int gmshModelGeoRemove(const std::vector<std::pair<int, int> > &dimTags,
+                       bool recursive)
+{
+}
+
+int gmshModelGeoRemoveAllDuplicates()
+{
+}
+
+int gmshModelGeoSynchronize()
+{
+  GModel::current()->getGEOInternals()->synchronize(GModel::current());
+  return 0;
+}
diff --git a/Common/gmsh.h b/Common/gmsh.h
index 5fd0bba0f8b894cf46d6eacd8d1acfa082cbd805..7750f8742b5e4f4bc9b2e1d06fecdb9a4c8bbdc9 100644
--- a/Common/gmsh.h
+++ b/Common/gmsh.h
@@ -91,8 +91,6 @@ GMSH_API gmshModelGeoAddEllipseArc(int &tag, int startTag, int centerTag, int ma
 GMSH_API gmshModelGeoAddSpline(int &tag, const std::vector<int> &vertexTags);
 GMSH_API gmshModelGeoAddBSpline(int &tag, const std::vector<int> &vertexTags);
 GMSH_API gmshModelGeoAddBezier(int &tag, const std::vector<int> &vertexTags);
-GMSH_API gmshModelGeoAddNurbs(int &tag, const std::vector<int> &vertexTags,
-                              const std::vector<double> &knots);
 GMSH_API gmshModelGeoAddLineLoop(int &tag, const std::vector<int> &edgeTags);
 GMSH_API gmshModelGeoAddPlaneSurface(int &tag, const std::vector<int> &wireTags);
 GMSH_API gmshModelGeoAddSurfaceFilling(int &tag, const std::vector<int> &wireTags,
@@ -102,21 +100,24 @@ GMSH_API gmshModelGeoAddVolume(int &tag, const std::vector<int> &shellTags);
 GMSH_API gmshModelGeoExtrude(const std::vector<std::pair<int, int> > &inDimTags,
                              double dx, double dy, double dz,
                              std::vector<std::pair<int, int> > &outDimTags,
-                             const std::vector<int> &numElements,
-                             const std::vector<double> &heights, bool recombine);
+                             const std::vector<int> &numElements=std::vector<int>(),
+                             const std::vector<double> &heights=std::vector<double>(),
+                             bool recombine=false);
 GMSH_API gmshModelGeoRevolve(const std::vector<std::pair<int, int> > &inDimTags,
                              double x, double y, double z,
                              double ax, double ay, double az, double angle,
                              std::vector<std::pair<int, int> > &outDimTags,
-                             const std::vector<int> &numElements,
-                             const std::vector<double> &heights, bool recombine);
+                             const std::vector<int> &numElements=std::vector<int>(),
+                             const std::vector<double> &heights=std::vector<double>(),
+                             bool recombine=false);
 GMSH_API gmshModelGeoTwist(const std::vector<std::pair<int, int> > &inDimTags,
                            double x, double y, double z,
                            double dx, double dy, double dz,
                            double ax, double ay, double az, double angle,
                            std::vector<std::pair<int, int> > &outDimTags,
-                           const std::vector<int> &numElements,
-                           const std::vector<double> &heights, bool recombine);
+                           const std::vector<int> &numElements=std::vector<int>(),
+                           const std::vector<double> &heights=std::vector<double>(),
+                           bool recombine=false);
 GMSH_API gmshModelGeoTranslate(const std::vector<std::pair<int, int> > &dimTags,
                                double dx, double dy, double dz);
 GMSH_API gmshModelGeoRotate(const std::vector<std::pair<int, int> > &dimTags,
diff --git a/utils/api_demos/CMakeLists.txt b/utils/api_demos/CMakeLists.txt
index dc5c58756d7b303a7fa650ae64465e40e40d3479..b5aff3c4cba039e9e3c7230227032f29cf16fb6e 100644
--- a/utils/api_demos/CMakeLists.txt
+++ b/utils/api_demos/CMakeLists.txt
@@ -25,3 +25,6 @@ target_link_libraries(basic ${GMSH_LIB} ${LAPACK_LIB} ${BLAS_LIB})
 
 add_executable(basic2 basic2.cpp)
 target_link_libraries(basic2 ${GMSH_LIB} ${LAPACK_LIB} ${BLAS_LIB})
+
+add_executable(t1 t1.cpp)
+target_link_libraries(t1 ${GMSH_LIB} ${LAPACK_LIB} ${BLAS_LIB})
diff --git a/utils/api_demos/t1.cpp b/utils/api_demos/t1.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..231192d21d369b1b366f4d4d1e15af2517a4daf0
--- /dev/null
+++ b/utils/api_demos/t1.cpp
@@ -0,0 +1,46 @@
+#include <iostream>
+#include <gmsh.h>
+
+// this reimplements gmsh/tutorial/t1.geo
+
+int main(int argc, char **argv)
+{
+  gmshInitialize(argc, argv);
+  gmshOptionSetNumber("General.Terminal", 1);
+  gmshModelCreate("t1");
+
+  double lc = 1e-2;
+  int tag;
+  tag = 1; gmshModelGeoAddVertex(tag, 0, 0, 0, lc);
+  tag = 2; gmshModelGeoAddVertex(tag, .1, 0,  0, lc);
+  tag = 3; gmshModelGeoAddVertex(tag, .1, .3, 0, lc);
+  tag = 4; gmshModelGeoAddVertex(tag, 0,  .3, 0, lc);
+
+  tag = 1; gmshModelGeoAddLine(tag, 1, 2);
+  tag = 2; gmshModelGeoAddLine(tag, 3, 2);
+  tag = 3; gmshModelGeoAddLine(tag, 3, 4);
+  tag = 4; gmshModelGeoAddLine(tag, 4, 1);
+
+  std::vector<int> l;
+  l.push_back(4); l.push_back(1); l.push_back(-2); l.push_back(3);
+  tag = 1; gmshModelGeoAddLineLoop(tag, l);
+
+  std::vector<int> ll;
+  ll.push_back(1);
+  tag = 1; gmshModelGeoAddPlaneSurface(tag, ll);
+
+  std::vector<int> p;
+  p.push_back(1); p.push_back(2);
+  gmshModelAddPhysicalGroup(0, 1, p);
+  gmshModelAddPhysicalGroup(1, 2, p);
+  p.clear(); p.push_back(1);
+  gmshModelAddPhysicalGroup(2, 6, p);
+  gmshModelSetPhysicalName(2, 6, "My surface");
+
+  gmshModelGeoSynchronize();
+  gmshModelMesh(2);
+
+  gmshExport("t1.msh");
+  gmshFinalize();
+  return 0;
+}