diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index 0e9eb8082bfa5a7e32d8d5a787d30fbbbf862136..1496b4b6383c449658a01cda8378eab67da1e864 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -1262,7 +1262,7 @@ int gmshModelOccSynchronize()
 
 // gmshModelField
 
-int gmshModelFieldAdd(const int tag, const std::string &type)
+int gmshModelFieldCreate(const int tag, const std::string &type)
 {
   if(!isInitialized()) return -1;
 #if defined(HAVE_MESH)
diff --git a/Common/gmsh.h b/Common/gmsh.h
index b93f256413ef28c94a94ede777540681c407d8f4..2a5981ef276ce34e0f8707806baaf59d1aeb915e 100644
--- a/Common/gmsh.h
+++ b/Common/gmsh.h
@@ -293,7 +293,7 @@ GMSH_API gmshModelOccSynchronize();
 
 // gmshModelField
 
-GMSH_API gmshModelFieldAdd(const int tag, const std::string &type);
+GMSH_API gmshModelFieldCreate(const int tag, const std::string &type);
 GMSH_API gmshModelFieldSetNumber(const int tag, const std::string &option,
                                  const double value);
 GMSH_API gmshModelFieldSetString(const int tag, const std::string &option,
@@ -303,9 +303,7 @@ GMSH_API gmshModelFieldSetNumbers(const int tag, const std::string &option,
 GMSH_API gmshModelFieldSetAsBackground(const int tag);
 GMSH_API gmshModelFieldDelete(const int tag);
 
-// gmshSolver
-
-// gmshPost
+// gmshView
 
 // gmshPlugin
 
diff --git a/Common/gmsh.i b/Common/gmsh.i
index 8ecb365412e2934f63c342882aeabab3b6929d71..bad364b2858c8983655ffc2a97266f293bbd77e4 100644
--- a/Common/gmsh.i
+++ b/Common/gmsh.i
@@ -1,15 +1,20 @@
 %module gmsh
+%include typemaps.i
+// reference to int is appended to the returned values of the function
+%apply int &OUTPUT { int &outTag };
 %{
   #include "gmsh.h"
 %}
 
 %include std_string.i
 %include std_vector.i
+%include std_pair.i
 
-namespace std {
-  %template(DoubleVector) vector<double>;
-  %template(StringVector) vector<string>;
-  %template(PairVector) vector<std::pair<int, int> >;
-}
+%template() std::pair<int, int>;
+%template(IntVector) std::vector<int>;
+%template(DoubleVector) std::vector<double>;
+%template(StringVector) std::vector<std::string>;
+%template(PairVector) std::vector<std::pair<int, int> >;
+%template(PairVectorVector) std::vector<std::vector<std::pair<int, int> > >;
 
 %include "gmsh.h"
diff --git a/demos/api/t1.py b/demos/api/t1.py
new file mode 100644
index 0000000000000000000000000000000000000000..c2493c71cea4e0c33fa9ab3564b559221fa4ac17
--- /dev/null
+++ b/demos/api/t1.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+
+# This file reimplements gmsh/tutorial/t1.geo in Python. For all the elementary
+# explanations about the general philosphy of entities in Gmsh, see the
+# comments in the .geo file. Comments here will focus on the specifics of the
+# Python API.
+
+# The Gmsh API is entirely defined in the gmsh module
+from gmsh import *
+
+# Before using any functions in the Python API, Gmsh must be initialized. If
+# argc/argv are passed, Gmsh will parse the commandline in the same way as the
+# standalone Gmsh code.
+gmshInitialize();
+
+# By default Gmsh will not print out any messages: in order to output messages
+# on the terminal, just set the standard Gmsh option "General.Terminal" (same
+# format and meaning as in .geo files) using gmshOptionSetNumber():
+gmshOptionSetNumber("General.Terminal", 1);
+
+# This creates a new model, named "t1". If gmshModelCreate() is not called, a
+# new default (unnamed) model will be created on the fly, if necessary.
+gmshModelCreate("t1");
+
+# The C++ API provides direct access to the internal CAD kernels. The built-in
+# CAD kernel was used in t1.geo: the corresponding API functions have the
+# "gmshModeGeo" prefix. To create geometrical points with the built-in CAD
+# kernel, one thus uses gmshModelGeoAddPoint():
+#
+# - the first argument is the point tag ; if positive, the point is created with
+#   this tag ; if negative, a new (unused) tag will be assigned and returned as
+#   the second value after the return code, i.e. gmshModelGeoAddPoint(3, .1, .3,
+#   0, lc) will return [0 3]
+#
+# - the next 3 arguments are the point coordinates (x, y, z)
+#
+# - the last (optional) argument is the target mesh size close to the point
+
+lc = 1e-2;
+gmshModelGeoAddPoint(1, 0, 0, 0, lc);
+gmshModelGeoAddPoint(2, .1, 0,  0, lc);
+gmshModelGeoAddPoint(3, .1, .3, 0, lc);
+gmshModelGeoAddPoint(4, 0, .3, 0, lc);
+
+# The API to create lines with the built-in kernel follows the same conventions:
+# the first argument is a tag (here positive to force it), followed by 2 point
+# tags, followed by the actual (returned) tag.
+gmshModelGeoAddLine(1, 1, 2);
+gmshModelGeoAddLine(2, 3, 2);
+gmshModelGeoAddLine(3, 3, 4);
+gmshModelGeoAddLine(4, 4, 1);
+
+
+# The philosophy to construct line loops and surfaces is similar: the second
+# arguments are now vectors of integers.
+gmshModelGeoAddLineLoop(1, [4, 1, -2, 3]);
+gmshModelGeoAddPlaneSurface(1, [1]);
+
+# Physical groups are defined by providing the dimension of the group (0 for
+# physical points, 1 for physical lines, 2 for physical surfaces and 3 for
+# phsyical volumes) and its tag, followed by a vector of entity tags.
+gmshModelAddPhysicalGroup(0, 1, [1, 2]);
+gmshModelAddPhysicalGroup(1, 2, [1, 2]);
+gmshModelAddPhysicalGroup(2, 6, [1]);
+
+# Physical names are also defined by providing the dimension and tag of the
+# entity.
+gmshModelSetPhysicalName(2, 6, "My surface");
+
+# Before it can be meshed, the internal CAD representation must be synchronized
+# with the Gmsh model, which will create the relevant Gmsh data structures. This
+# is achieved by the gmshModelGeoSynchronize() API call for the built-in CAD
+# kernel. Synchronizations can be called at any time, but they involve a non
+# trivial amount of processing; so while you could synchronize the internal CAD
+# data after every CAD command, it is usually better to minimize the number of
+# synchronization points.
+gmshModelGeoSynchronize();
+
+# We can then generate a 2D mesh...
+gmshModelMesh(2);
+
+# ... and save it to disk
+gmshExport("t1.msh");
+
+# This should be called at the end:
+gmshFinalize();
diff --git a/demos/api/t2.py b/demos/api/t2.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a4181126f246e4afd924eb7d615cf0d74557732
--- /dev/null
+++ b/demos/api/t2.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+
+# This file reimplements gmsh/tutorial/t2.geo in Python. Comments focus on the new
+# API functions used, compared to the ones introduced in t1.py.
+
+from gmsh import *
+
+gmshInitialize();
+gmshOptionSetNumber("General.Terminal", 1);
+
+gmshModelCreate("t2");
+
+# Copied from t1.cpp...
+lc = 1e-2;
+gmshModelGeoAddPoint(1, 0, 0, 0, lc);
+gmshModelGeoAddPoint(2, .1, 0,  0, lc);
+gmshModelGeoAddPoint(3, .1, .3, 0, lc);
+gmshModelGeoAddPoint(4, 0,  .3, 0, lc);
+
+gmshModelGeoAddLine(1, 1, 2);
+gmshModelGeoAddLine(2, 3, 2);
+gmshModelGeoAddLine(3, 3, 4);
+gmshModelGeoAddLine(4, 4, 1);
+
+gmshModelGeoAddLineLoop(1, [4, 1, -2, 3]);
+gmshModelGeoAddPlaneSurface(1, [1]);
+gmshModelAddPhysicalGroup(0, 1, [1, 2]);
+gmshModelAddPhysicalGroup(1, 2, [1, 2]);
+gmshModelAddPhysicalGroup(2, 6, [1]);
+gmshModelSetPhysicalName(2, 6, "My surface");
+# ...end of copy
+
+gmshModelGeoAddPoint(5, 0, .4, 0, lc);
+gmshModelGeoAddLine(5, 4, 5);
+
+# Geometrical transformations take a vector of pairs of integers as first
+# argument, which contains the list of entities, represented by (dimension, tag)
+# pairs. Here we thus translate point 3 (dimension=0, tag=3), by dx=-0.05, dy=0,
+# dz=0.
+gmshModelGeoTranslate([(0, 3)], -0.05, 0, 0);
+
+# The "Duplicata" functionality in .geo files is handled by
+# gmshModelGeoCopy(), which takes a vector of (dim, tag) pairs as input, and
+# returns another vector of (dim, tag) pairs.
+
+ov = PairVector()
+gmshModelGeoCopy([(0, 3)], ov);
+gmshModelGeoTranslate(ov, 0, 0.1, 0);
+
+gmshModelGeoAddLine(7, 3, ov[0][1]);
+gmshModelGeoAddLine(8, ov[0][1], 5);
+gmshModelGeoAddLineLoop(10, [5,-8,-7,3]);
+gmshModelGeoAddPlaneSurface(11, [10]);
+
+gmshModelGeoCopy([(2, 1), (2, 11)], ov);
+gmshModelGeoTranslate(ov, 0.12, 0, 0);
+
+print "New surfaces '%d' and '%d'\n", ov[0][1], ov[1][1];
+
+gmshModelGeoAddPoint(100, 0., 0.3, 0.13, lc);
+gmshModelGeoAddPoint(101, 0.08, 0.3, 0.1, lc);
+gmshModelGeoAddPoint(102, 0.08, 0.4, 0.1, lc);
+gmshModelGeoAddPoint(103, 0., 0.4, 0.13, lc);
+
+gmshModelGeoAddLine(110, 4, 100);
+gmshModelGeoAddLine(111, 3, 101);
+gmshModelGeoAddLine(112, 6, 102);
+gmshModelGeoAddLine(113, 5, 103);
+gmshModelGeoAddLine(114, 103, 100);
+gmshModelGeoAddLine(115, 100, 101);
+gmshModelGeoAddLine(116, 101, 102);
+gmshModelGeoAddLine(117, 102, 103);
+
+gmshModelGeoAddLineLoop(118, [115, -111, 3, 110]);
+gmshModelGeoAddPlaneSurface(119, [118]);
+gmshModelGeoAddLineLoop(120, [111, 116, -112, -7]);
+gmshModelGeoAddPlaneSurface(121, [120]);
+gmshModelGeoAddLineLoop(122, [112, 117, -113, -8]);
+gmshModelGeoAddPlaneSurface(123, [122]);
+gmshModelGeoAddLineLoop(124, [114, -110, 5, 113]);
+gmshModelGeoAddPlaneSurface(125, [124]);
+gmshModelGeoAddLineLoop(126, [115, 116, 117, 114]);
+gmshModelGeoAddPlaneSurface(127, [126]);
+
+# The API to create surface loops ("shells") and volumes is similar to the
+# one used to create line loops and surfaces.
+gmshModelGeoAddSurfaceLoop(128, [127, 119, 121, 123, 125, 11]);
+gmshModelGeoAddVolume(129, [128]);
+
+# Extrusion works as expected, by providing a vector of (dim, tag) pairs as
+# input, the translation vector, and a vector of (dim, tag) pairs as output.
+ov2 = PairVector()
+gmshModelGeoExtrude([ov[1]], 0, 0, 0.12, ov2);
+
+# Mesh sizes associated to geometrical points can be set by passing a vector of
+# (dim, tag) pairs for the corresponding points.
+
+gmshModelGeoSetMeshSize([(0,103), (0,105), (0,109), (0,102), (0,28),
+                         (0, 24), (0,6), (0,5)], lc * 3);
+
+gmshModelAddPhysicalGroup(3, 1, [129,130]);
+gmshModelSetPhysicalName(3, 1, "The volume");
+
+gmshModelGeoSynchronize();
+
+gmshModelMesh(3);
+
+gmshExport("t2.msh");
+
+gmshFinalize();