Creating Your First Booking

In this tutorial, you’ll create your first Booking, Customer, and Departure Service through the G Adventures API.

Now that you’re displaying trips from the G Adventures API, it’s time for the next step; Getting customers booked on trips.

When you wish to book a customer on a trip, you’ll be booking them on a departure service, but before we can do that we must create the booking, as well as the customer. Let’s review all these steps and book a customer on a trip.

When building out a checkout journey, we recommend creating the customers and services before taking payment. The following flow is generally recommended:

  1. Customer selects one or more departure’s they’d like to book
  2. System requests customer information. For check out and confirmation, we recommend capturing the base needs always (e.g. Full legal names, country, date of birth, nationality). Your system can review the CONFIRMATION requirements of the selected departure’s if applicable and request those as well.
  3. Upon customer saving information, system creates booking, departure service(s) and customer(s).
  4. Customer is presented with a payment page if applicable. You can use our payments API, or you can take payment through Sherpa. By having created the departure service prior to payment, you are also able to display deposit information on payment page from reading the departure service object. See Deposits for more info.
  5. Customer is presented with confirmation page with Booking number

Ensuring Your Agency Status Is Setup

For an Application in the G Adventures API to create bookings, it must be bound to an Agency Code. An Agency Code is a unique set of digits that is bound to your particular agency. Generally, if you are looking to book services via the G Adventures API then you will have spoken to a sales representative from G Adventures who has worked with you to setup a contract. If this is something you need to accomplish, we do recommend sending us an email to begin this conversation.

To add your Agency Code to your application, simply visit your application dashboard and modify this value:

../_images/agency-code.png

Once it’s been modified, you will receive an email to confirm that you are the owner of this application, and will be able to authorize its usage against your agency. This is an important step in order to ensure the security of your data.

Once authorized, you will be able to create services and bookings via the test environment. This will allow you to do everything referenced in the tutorial below. Once you’ve completed your integration and are looking to release it in production, you can email us to begin the process of authorizing your application for production release.

Creating The Booking

Bookings within the G API are simply containers for one or more service. A service can be a departure service, activity service, transport service, and so on. Since the booking is just a container, the details necessary to create one are fairly slim.

POST /bookings/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "currency": "CAD",
    "external_id": "FUN1"
}

That’s it! You’ll receive a response from the G Adventures API with a few more details, that will look like so:

HTTP/1.1 201 CREATED
Content-Type: application/json

{
  "id": "628360",
  "href": "https://rest.gadventures.com/bookings/628360/"
  "external_id": "FUN1",
  "currency": "CAD",
  "date_created": "2017-09-13T17:18:06Z",
  "date_closed": null,
  "date_of_first_travel": "2017-09-13",
  "date_of_last_travel": "2017-09-13",
  "balance_due_date": "2017-09-13",
  "amount_paid": "0.00",
  "amount_owing": "0.00",
  "commission": "0.00",
  "tax_on_commission": "0.00",
  "agent": {
      "id": "49284",
      "href": "https://rest.gadventures.com/agents/49284"
  },
  "services": {
      "href": "https://rest.gadventures.com/bookings/628360/services"
  },
  "invoices": {
      "href": "https://rest.gadventures.com/bookings/628360/invoices"
  },
  "payments": {
      "href": "https://rest.gadventures.com/bookings/628360/payments"
  },
  "refunds": {
      "href": "https://rest.gadventures.com/bookings/628360/refunds"
  }
}

At this point, you are able to query the new Booking through the API. If unsure of a specific attribute in the response, please see the bookings reference.

Next step, is to create the customer. A customer is not attached directly to a Booking, so you will notice in the request that the newly created Booking is not referenced.

Creating The Customer

The minimal set of details necessary for a customer are referenced in this request:

POST /customers/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "name": {
        "legal_first_name": "G",
        "legal_last_name": "Corp",
        "title": "Mr"
    },
    "date_of_birth": "1980-10-05",
    "account_email": "g.corp@gadventures.com"
}

And the response will contain the full customer representation.

HTTP/1.1 201 CREATED
Content-Type: application/json

{
    "id": "1323083",
    "href": "/customers/1323083",
    "name": {
        "legal_first_name": "G",
        "legal_last_name": "Corp",
        "legal_middle_name": null,
        "common_name": null,
        "title": "Mr"
    },
    "date_of_birth": "1980-10-05",
    "place_of_birth": null,
    "nationality": null,
    "passport": {
        "number": null,
        "issue_date": null,
        "expiry_date": null,
        "place_of_issue": null
    },
    "meal_preference": null,
    "meal_notes": null,
    "account_email": "g.corp@gadventures.com",
    "phone_numbers": null,
    "emergency_contacts": {
        "first_name": null,
        "last_name": null,
        "phone_numbers": null
    },
    "address": {
        "street": null,
        "city": null,
        "state": null,
        "country": null,
        "postal_zip": null,
        "latitude": null,
        "longitude": null
    },
    "bookings": {
        "href": "/customers/1323083/bookings"
    }
}

Finally, we’re going to compile all of this under a Departure Service.

Creating The Departure Service

Now, it’s time to piece everything together. We want to sell a specific departure. To do this, we use the departure service. Every service can have one or more customers on it, and is associated with a single booking. Once the departure service is created, availability of the related departure will be affected.

Let’s look at how that looks.

POST /departure_services/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "booking": {
        "id": "628360"
    },
    "product": {
        "id": "420482"
    },
    "customers": [
        {
            "id": "1323083"
        }
    ]
}

And the response will of course, contain the full representation of the Departure Service.

HTTP/1.1 201 CREATED
Content-Type: application/json

{
    "id": "1162343",
    "href": "/departure_services/1162343",
    "name": "Indochina Discovery",
    "status": "Option",
    "status_transitions": ["Expired"],
    "type": "departure_services",
    "sub_type": "Tour",
    "start_date": "2013-12-07",
    "finish_date": "2014-01-05",
    "customers": {
        "id": "1323083",
        "href": "/customers/1323083",
        "name": {
            "legal_first_name": "G",
            "legal_last_name": "Corp",
            "legal_middle_name": null,
            "common_name": null,
            "title": "Mr"
        },
    },
    "date_created": "2013-09-13T18:42:47Z",
    "date_confirmed": null,
    "date_cancelled": null,
    "option_expiry_date": "2013-09-17T18:42:46Z",
    "purchase_price": "2549.00",
    "commission": "0.00",
    "applied_promotion": {
        "id": "25358",
        "name": "Promo for CAD",
        "promotion_code": "PFCAD",
        "discount_amount": "100.00",
        "commission_rate": null,
        "terms_and_conditions": null
    },
    "flags": [],
    "booking": {
        "id": "628360",
        "href": "/bookings/628360"
    },
    "documents": null,
    "product": {
        "id": "420482",
        "href": "/departures/420482",
        "name": "Indochina Discovery"
    },
    "rooms": {
        "code": "STANDARD",
        "name": "Standard",
        "customer": null
    },
    "incomplete_requirements": [
        {
            "type": "CONFIRMATION",
            "name": "Nationality",
            "code": "NATIONALITY",
            "message": "Nationality must be submitted for this product. 'nationality' must be set in the customer resource.",
            "customer": {
                "id": "1323083",
                "href": "/customers/1323083",
                "name": {
                    "legal_first_name": "G",
                    "legal_last_name": "Corp",
                    "legal_middle_name": null,
                    "common_name": null,
                    "title": "Mr"
                },
            }
        },
    ],
    "arrival_flight_details": [],
    "departure_flight_details": [],
    "international_ticket_numbers": [],
    "traveller_heights": []
}

At this point, you have successfully booked a customer on a specific Departure. You’ll see that the Departure Service has a status of Option. You can Confirm a service by reviewing the incomplete_requirements and updating the relevant customer records to meet those requirements. For further information, please review the departure service documentation.

Handling Merged Customers When Creating Services

At times, when creating the Departure Service (or technically, any service), you’ll receive a response which looks like the following:

HTTP/1.1 410 GONE
Content-Type: application/json

{
    "message": "Customer 1941170 was merged with customer 1940018. Please
      re-submit your request with customer 1940018.",
     "errors": [
      {
        "code": "MERGED_RECORD",
        "field": "customer.id",
        "value": 1940018
      }
     ],
     "time": "2017-10-01T20:08:30",
     "http_status_code": 410
}

This can occur if the customer you are referencing or have created (even very recently) was merged with another customer in the G Adventures API.

The reasoning for this is because upon creation of a customer, an asynchronous process is run to ensure the customer is not created as a duplicate within our reservation system, thus ensuring your data is clean and accurate. If a duplicate is found, the customer record you just created will now redirect to an existing customer record, that was found by this duplicate identification process.

There’s two approaches you can take to work around this.

First, you can do a GET request on the customer.id you’ll be passing into the creation of the service object. Upon doing the GET, you will either receive a 200 OK or a 301 Redirect. If you receive the latter, it means this customer was indeed merged and you’ll be redirected to the new customer.

Once redirected, you can capture the new customer id and use that in the creation of your service. Essentially, the flow is like so:

  • GET /customers/{id}
  • Redirected With 301? Capture customer id from response
  • Not Redirected? Don’t change anything
  • POST service with whatever customer id is relevant (same, or redirected)

Note that many HTTP clients within frameworks do auto-redirect of 301 and in some cases make that action invisible to the developer.

Another solution for this is to have exception handling for this scenario. Capture the 410 GONE status code and identify if MERGED_RECORD is within code attribute for the errors list.

Once you’ve identified the exception, you can take the new Customer ID from the value field, and re-post your Departure Service with it, just like you had previously.