NAME
WebService::HMRC::VAT - Interact with the UK HMRC VAT API
VERSION
Version 0.04
SYNOPSIS
use WebService::HMRC::VAT;
my $vat = WebService::HMRC::VAT->new({
vrn => '123456789'
});
$vat->auth->access_token('MY-ACCESS-TOKEN');
# Display outstanding VAT returns
my $result = $vat->obligations({
from => '2018-01-01',
to => '2018-12-31',
state => 'O',
});
if($result->is_success) {
foreach my $o (@{$result->data->{obligations}) {
print "VAT return " . $o->{periodKey};
print " due " . $o->{due} . "\n";
}
}
# Submit a VAT return
$result = $vat->submit_return({
periodKey => "#001", # from ->obligations()
vatDueSales => 100.00, # Box 1 on paper form
vatDueAcquisitions => 100.00, # Box 2 on paper form
totalVatDue => 200.00, # Box 3 on paper form
vatReclaimedCurrPeriod => 100.00, # Box 4 on paper form
netVatDue => 100.00, # Box 5 on paper form
totalValueSalesExVAT => 500, # Box 6 on paper form
totalValuePurchasesExVAT => 500, # Box 7 on paper form
totalValueGoodsSuppliedExVAT => 500, # Box 8 on paper form
totalAcquisitionsExVAT => 500, # Box 9 on paper form
finalised => 1, # Boolean user declaration
});
if($result->is_success) {
print "VAT Return submitted:\n"
printf "Receipt ID: %s\n", $result->header('Receipt-ID');
printf "Form Bundle: %s\n", $result->data->{formBundleNumber};
}
DESCRIPTION
Perl module to interact with the UK's HMRC Making Tax Digital `VAT` API. This allows VAT returns to be submitted or viewed, and obligations, payments and liabilities to be viewed.
For more information, see: https://developer.service.hmrc.gov.uk/api-documentation/docs/api/service/vat-api/1.0
REQUIRES
EXPORTS
Nothing
PROPERTIES
Inherits from WebService::HMRC::Request.
vrn
VAT registration number for which records are being queries or submitted. Required parameter for initialisation.
The VAT registration number must be purely numeric, without any spaces or GB prefix.
METHODS
Inherits from WebService::HMRC::Request.
obligations({ from => 'YYYY-MM-DD', to => 'YYYY-MM-DD', [status => $status, ] [test_mode => $test_mode] })
Retrieve a set of VAT filing obligations for the specified date range. Returns a WebService::HMRC::Response object reference. Requires permission for the read:vat
service scope.
Parameters
- from
-
Return obligations from this date, specified as YYYY-MM-DD. Required parameter.
- to
-
Return obligations up to this date, specified as YYYY-MM-DD. Required parameter.
- status
-
Optional parameter to filter the obligations returned. May be set to 'O' to return only 'open' obligations, or 'F' to return only 'fulfilled' obligations.
Default is to return all obligations, both fulfilled and open.
- test_mode
-
Optional parameter used only for testing against the HMRC sandbox api.
This parameter should not be used in production systems - it causes dummy test data to be returned.
By default, when testing against the sandbox with no
test_mode
specified, the test api simulates the scenario where the client has quarterly obligations and one is fulfilledOther test scenarios are available by setting the
test_mode
parameter as detailed below:QUARTERLY_NONE_MET
simulates the scenario where the client has quarterly obligations and none are fulfilled.QUARTERLY_ONE_MET
simulates the scenario where the client has quarterly obligations and one is fulfilled.QUARTERLY_TWO_MET
simulates the scenario where the client has quarterly obligations and two are fulfilled.QUARTERLY_THREE_MET
simulates the scenario where the client has quarterly obligations and three are fulfilled.QUARTERLY_FOUR_MET
simulates the scenario where the client has quarterly obligations and four are fulfilled.MONTHLY_NONE_MET
simulates the scenario where the client has monthly obligations and none are fulfilled.MONTHLY_ONE_MET
simulates the scenario where the client has monthly obligations and one month is fulfilled.MONTHLY_TWO_MET
simulates the scenario where the client has monthly obligations and two months are fulfilled.MONTHLY_THREE_MET
simulates the scenario where the client has monthly obligations and three months are fulfilled.NOT_FOUND
simulates the scenario where no data is found.
Response Data
For full details of the response data, see the HMRC API specification. In summary, the data contains a single element `obligations` pointing to an array of VAT return obligations:
{
obligations => [
{
periodKey => "#001"
start => "2017-04-06",
end => "2017-07-05",
due => "2017-08-12",
status => "F",
received => "2017-08-05", # only present if 'Fulfilled'
},
{
periodKey => "#004"
start => "2018-01-06",
end => "2018-04-05",
due => "2018-05-12",
status => "O",
},
]
}
Example usage
my $result = $vat->obligations({
from => '2018-01-01',
to => '2018-12-31',
});
foreach my $obligation( @{$result->data->{obligations}} ) {
print "-- VAT Return Obligation --\n"
print " ID: $obligation->{periodKey}\n";
print " Period Start: $obligation->{start}\n";
print " Period End: $obligation->{end}\n";
print " Due Date: $obligation->{due}\n";
print "Received Date: ";
if ($obligation->{status} eq 'F') {
print "$obligation->{received}\n";
}
else {
print "Still Outstanding\n";
}
}
liabilities({ from => 'YYYY-MM-DD', to => 'YYYY-MM-DD', [test_mode => $test_mode] })
Retrieve a set of VAT payment liabilities. Returns a WebService::HMRC::Response object reference. Requires permission for the read:vat
service scope.
Parameters
- from
-
Return liabilities from this date, specified as YYYY-MM-DD. Required parameter. The date must be before today's date, otherwise the api will return an error.
- to
-
Return liabilities up to this date, specified as YYYY-MM-DD. Required parameter.
- test_mode
-
Optional parameter used only for testing against the HMRC sandbox api.
If set to
SINGLE_LIABILITY
, returns a single valid liability when used with dates from 2017-01-02 and to 2017-02-02.If set to
MULTIPLE_LIABILITIES
, returns multiple valid liabilities when used with dates from 2017-04-05 and to 2017-12-21.This parameter should not be used in production systems - it causes dummy test data to be returned.
Response Data
For full details of the response data, see the HMRC API specification. In summary, the data contains a single element `liabilities` pointing to an array of VAT payment liabilities:
{
liabilities => [
{
taxPeriod => {
from => "2017-04-06",
to => "2017-07-06"
},
type => "VAT ...",
originalAmount => 6000.00,
outstandingAmount => 100.00,
due => "2017-07-06"
},
]
}
Example usage
my $result = $vat->liabilities({
from => '2018-01-01',
to => '2018-03-31',
});
foreach my $liability( @{$result->data->{liabilities}} ) {
print "-- VAT Payment Liability --\n"
print " Type: $liability->{type}\n";
print " Period Start: $liability->{taxPeriod}->{from}\n";
print " Period End: $liability->{taxPeriod}->{to}\n";
print "Original Amount: $liability->{originalAmount}\n";
print " Due Amount: $liability->{outstandingAmount}\n";
print " Due Date: $liability->{due}\n";
}
payments({ from => 'YYYY-MM-DD', to => 'YYYY-MM-DD', [test_mode => $test_mode] })
Retrieve a set of payments received by HMRC in respect of VAT over the specified date range. Returns a WebService::HMRC::Response object reference. Requires permission for the read:vat
service scope.
Parameters
- from
-
Return payments from this date, specified as YYYY-MM-DD. Required parameter.
- to
-
Return payments up to this date, specified as YYYY-MM-DD. Required parameter.
- test_mode
-
Optional parameter used only for testing against the HMRC sandbox api.
If set to
SINGLE_PAYMENT
, returns a single valid payment when used with dates from 2017-01-02 and to 2017-02-02.If set to
MULTIPLE_PAYMENTS
, returns multiple valid payments when used with dates from 2017-02-27 and to 2017-12-21.This parameter should not be used in production systems - it causes dummy test data to be returned.
Response Data
For full details of the response data, see the HMRC API specification. In summary, the data contains a single element `payments` pointing to an array of payments received by HMRC:
{
payments => [
{
amount => 100.00,
received => "2017-04-06"
},
]
}
Example usage
my $result = $vat->payments(
from => '2018-01-01',
to => '2018-03-31',
);
foreach my $payment( @{$result->data->{payments}} ) {
print "-- VAT Payments Received by HMRC --\n"
print "Date Received: $payment->{received}\n";
print " Amount: $payment->{amount}\n";
}
get_return({ period_key => $period_key })
Retrieve a previously submitted VAT return corresponding to the supplied period_key. Returns a WebService::HMRC::Response object reference. Requires permission for the read:vat
service scope.
Parameters
- period_key
-
The ID code for the period that uniquely identifies a submitted VAT return, as contained within the response from an obligations() method call.
Response Data
For full details of the response data, see the HMRC API specification. In summary, the data is a hashref comprising the following elements which correspond to fields on the traditional paper VAT100 form:
{
periodKey => "#001",
vatDueSales => 100.00,
vatDueAcquisitions => 100.00,
totalVatDue => 200,
vatReclaimedCurrPeriod => 100.00,
netVatDue => 100,
totalValueSalesExVAT => 500,
totalValuePurchasesExVAT => 500,
totalValueGoodsSuppliedExVAT => 500,
totalAcquisitionsExVAT => 500
}
Note that some fields are returned as integers where only whole pounds are required to be submitted by HMRC.
submit_return($hashref)
Retrieve a previously submitted VAT return corresponding to the supplied period_key. Returns a WebService::HMRC::Response object reference. Requires permission for the write:vat
service scope.
Parameters
For full details of the required parameters and the rules for calculating each value, see the HMRC API specification and VAT documentation. The brief descriptions here are intended as a simplified overview to help understand the code and are not a comprehensive or necessarily accurate representation of VAT law.
In summary, the data is a hashref comprising the following elements which correspond to fields on the traditional paper VAT100 form. All parameters are required.
- period_key
-
The ID code for the period that uniquely identifies a submitted VAT return, as contained within the response from an obligations() method call.
- vatDueSales
-
VAT due on sales and other outputs. Corresponds to box 1 on the traditional VAT100 paper form.
- vatDueAcquisitions
-
VAT due on acquisitions from other EC member states as part of the reverse- charge scheme. Corresponds to box 2 on the traditional VAT100 paper form.
- totalVatDue
-
The sum of vatDueSales and vatDueAcquisitions. Corresponds to box 3 on the traditional VAT100 paper form.
- vatReclaimedCurrPeriod
-
VAT reclaimed on purchases and other inputs, including acquisitions from other EC member states. This corresponds to box 4 on the traditional VAT100 paper form.
- netVatDue
-
The absolute (unsigned, always positive) difference between totalVatDue and vatReclaimedCurrPeriod. This corresponds to box 5 on the traditional VAT100 paper form.
- totalValueSalesExVAT
-
Total value of sales and all other outputs, excluding any VAT, rounded to an integer value. This corresponds to box 6 on the traditional VAT100 paper form.
- totalValuePurchasesExVAT
-
Total value of purchases and all other inputs, excluding any VAT and including any exempt purchases. This corresponds to box 7 on the traditional VAT100 paper form.
- totalValueGoodsSuppliedExVAT
-
Total value of all supplies of goods (but not services) to other EC member states and costs directly related to that supply (such as freight or insurance), excluding any VAT. This corresponds to box 8 on the traditional VAT100 paper form.
- totalAcquisitionsExVAT
-
Total value of acquisitions of goods from other EC member states and directly related costs (such as freight or insurance), excluding any VAT. This corresponds to box 9 on the traditional VAT100 paper form.
- finalised
-
Boolean declaration that the data being submitted has been finalised and approved by the user. Must be true for successful submission.
This parameter is converted to a JSON()->true or JSON()->false boolean value before encoding to json for submission.
Defaults to false.
Response Headers
For full details of the response headers, see the HMRC API specification. In summary the headers confirm receipt of the submission, comprising:
- Receipt ID
-
Unique reference number returned for a submission.
- Receipt-Timestamp
-
ISO8601 format timestamp of the form '2018-02-14T09:32:15Z'.
- X-CorrelationId
-
Unique ID for this operation.
Response Data
For full details of the response data, see the HMRC API specification. In summary, the response data is a hashref with keys:
- processingDate
-
ISO8601 timestamp indicating the time that the submission was processed.
- formBundleNumber
-
Unique number representing the "Form Bundle" in which the submitted data has been stored by HMRC.
- paymentIndicator
-
Set to 'DD' if payment is due to HMRC and they hold a Direct Debit instruction for the client, 'BANK' if a repayment is due from HMRC and they hold bank details to make the repayment, otherwise this element is not present in the returned data.
- chargeRefNumber
-
Present only is payment is due to HMRC.
Example
my $result = $vat->submit_return({
periodKey => "#001",
vatDueSales => 100.00,
vatDueAcquisitions => 0.00,
totalVatDue => 100.00,
vatReclaimedCurrPeriod => 50.00,
netVatDue => 50.00,
totalValueSalesExVAT => 500,
totalValuePurchasesExVAT => 250,
totalValueGoodsSuppliedExVAT => 0,
totalAcquisitionsExVAT => 0,
finalised => 1,
})
if($result->is_success) {
print "==== VAT Return Submitted ====\n";
printf " Receipt ID: %s\n", $result->header('Receipt-ID');
printf " Receipt Timestamp: %s\n", $result->header('Receipt-Timestamp');
printf " Tracking ID: %s\n", $result->header('X-CorrelationId');
printf " Processing Date: %s\n", $result->data->{processingDate};
printf " Form Bundle: %s\n", $result->data->{formBundleNumber};
if($result->data->{paymentIndicator}) {
printf " Payment Indicator: %s\n", $result->data->{paymentIndicator};
}
if($result->data->{paymentIndicator}) {
printf " Charge Reference: %s\n", $result->data->{chargeRefNumber};
}
}
AUTHORISATION
Access to the HMRC Making Tax Digital VAT APIs requires that an application be registered with HMRC and enabled for this service. Additionally permission must be granted by a registered user for the application to access the read:vat
or write:vat
service scope, as noted for each method.
Authorisation is provided by means of an access token
.
For more details on obtaining and using access tokens, See WebService::HMRC::Authenticate.
Further information, application credentials and documentation may be obtained from the HMRC Developer Hub.
TESTING
The basic tests are run as part of the installation instructions shown above use an invalid uri as an endpoint. This tests basic interaction with the module's method and does not require an internet connection.
Developer pre-release tests may be run with the following command:
prove -l xt/
With a working internet connection, HMRC application credentials and an access token granted by a test user enrolled for the Making Tax Digital for Business VAT service, interaction with the real HMRC sandbox api can be tested. The test user's VAT registration number must also be provided.
The credentials are specified as environment variables when running the tests:
HMRC_ACCESS_TOKEN=[MY-ACCESS-TOKEN] \
HMRC_VRN=[USER-VAT-REGISTRATION-NUMBER] \
make test TEST_VERBOSE=1
AUTHOR
Nick Prater, <nick@npbroadcast.com>
BUGS
Please report any bugs or feature requests to bug-webservice-hmrc-vat at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=WebService-HMRC-VAT. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT AND DOCUMENTATION
You can find documentation for this module with the perldoc command.
perldoc WebService::HMRC::VAT
The README.pod
file supplied with this distribution is generated from the WebService::HMRC::VAT module's pod by running the following command from the distribution root:
perldoc -u lib/WebService/HMRC/VAT.pm > README.pod
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
http://rt.cpan.org/NoAuth/Bugs.html?Dist=WebService-HMRC-VAT
CPAN Ratings
Search CPAN
Github
ACKNOWLEDGEMENTS
This module was originally developed for use as part of the LedgerSMB open source accounting software.
LICENSE AND COPYRIGHT
Copyright 2018-2019 Nick Prater, NP Broadcast Limited.
This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
http://www.perlfoundation.org/artistic_license_2_0
Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.