/// <summary>
        ///     Creates a person asyncronously.
        /// </summary>
        /// <param name="update">The values used to create the person</param>
        /// <param name="cancellationToken">Token allowing the request to be cancelled</param>
        /// <returns>The full represenation of the created person and their precinct</returns>
        public async Task <CreatePersonResponse> CreateAsync(PersonUpdate update, CancellationToken cancellationToken = default(CancellationToken))
        {
            Ensure.IsNotNull(update, nameof(update));

            var url     = UrlProvider.GetV1PersonCreateUrl();
            var content = ObjectChangesJsonSerializer.SerializeChangesToJson(null, new CreatePersonRequest(update));

            return((await PostJsonAsync <CreatePersonResponse>(url, content, cancellationToken, true)).Payload);
        }
        /// <summary>
        ///     Updates a person with the provided id to have the provided data syncronously. It returns a full representation of
        ///     the updated person.
        /// </summary>
        /// <param name="personId">The ID of the person to update</param>
        /// <param name="update">The values to update</param>
        /// <param name="cancellationToken">Token allowing the request to be cancelled</param>
        /// <returns>The full represenation of the updated person and their precinct</returns>
        public UpdatePersonResponse Update(int personId, PersonUpdate update,
                                           CancellationToken cancellationToken = default(CancellationToken))
        {
            Ensure.IsNotNull(update, nameof(update));

            var url     = UrlProvider.GetV1PersonUpdateUrl(personId);
            var content = ObjectChangesJsonSerializer.SerializeChangesToJson(null, new UpdatePersonRequest(update));

            return(PutJson <UpdatePersonResponse>(url, content, cancellationToken, true).Payload);
        }
        /// <summary>
        ///     Attempts to match the input person resource to a person already in the nation asyncronously.
        ///     If a match is found, the matched person is updated (without overriding data).
        ///     If a match is not found, a new person is created. Matches are found using one of the following IDs:
        ///     CiviCrmId, CountyFileId, CatalistId, ExternalId, Email, FacebookUsername, NgpId, SalesForceId, TwitterLogin, VanId.
        /// </summary>
        /// <param name="update">The values to update / match on</param>
        /// <param name="cancellationToken">Token allowing the request to be cancelled</param>
        /// <returns>The full represenation of the updated person, their precinct and whether they were created or updated</returns>
        public async Task <AddPersonResponse> AddAsync(PersonUpdate update,
                                                       CancellationToken cancellationToken = default(CancellationToken))
        {
            Ensure.IsNotNull(update, nameof(update));

            var url      = UrlProvider.GetV1PersonAddUrl();
            var content  = ObjectChangesJsonSerializer.SerializeChangesToJson(null, new UpdatePersonRequest(update));
            var response = await PutJsonAsync <AddPersonResponse>(url, content, cancellationToken, true);

            response.Payload.WasNewPersonCreated = response.HttpStatusCode == HttpStatusCode.Created;
            return(response.Payload);
        }