Quick start

The QuickBooks PHP SDK makes it easier for PHP developers to create apps for the QuickBooks Online APIs. This page describes how to create your integration, including features you will most likely want in your app.

Preliminaries

Use the links below to install the SDK, access the installation instructions, and view important information about the SDK.

    Developing an app using the PHP SDK

    The following are typical steps for developing an app using the PHP SDK:

    1. If you haven't already created an Intuit Developer account, create your account.
    2. Create your app on developer.intuit.com to get your development and production keys and URIs.
    3. Use API Explorer, Postman, and OAuth 2.0 Playground to explore and test the QuickBooks API and OAuth 2.0. For example code, see the PHP sample apps and the _Samples directory of the PHP SDK repository. For additional tools, see third-party tools.
    4. In your PHP developer environment, create your web app. You have the option to use Harmony Design System to create a user experience that makes your integration with QuickBooks Online look seamless. For a real-time, open-source, API-driven A/B Testing platform, see Wasabi.
    5. Set up Authorization and implement the Connect to QuickBooks button in your app.
    6. Configure your PHP SDK settings:
      1. Configure the base URL for either Sandbox or Production.
      2. Check the latest minor version supported and set this in your config file.
      3. Configure logging in the sdk.config file or in your code. 
    7. Use your development keys for developing and testing your app in the sandbox, or production keys for Production or Live QuickBooks Online company testing. Production keys can be obtained from the Keys tab under the Production tab of the app.
    8. Make sure that you set a unique requestId for each API call.
    9. Use the Class Library Reference to get details for the supported fields, functions, and classes provided by the PHP SDK.
    10. For details on how to make QuickBooks API calls, see Making QuickBooks API Calls.

    Setting up authorization

    For your app to access a user's data, the app redirects the user to Intuit's OAuth 2.0 server for authentication. The server authenticates the user and redirects them back to your app's OAuth 2.0 redirect URL with an authorization code, which is exchanged for an access token. Your application can use the access token to call QuickBooks APIs. You must refresh the token before each call to the QuickBooks API. For more information on setting up OAuth authorization, see Authorization. Use the OAuth 2.0 playground to experiment with the OAuth 2.0 protocol and QuickBooks Online APIs. It is pre-configured to use with Intuit's OAuth 2.0 endpoints so you can quickly get started.

    Testing your OAuth settings

    To test your configuration and confirm that you can successfully connect to QuickBooks Online, use the getCompanyInfo() method, which returns the CompanyInfo object representing the current company if successful, or null if unsuccessful. If the result is null, use getLastError() to get the specific error. The following example shows how to test you settings:

    $CompanyInfo = $dataService->getCompanyInfo();
    $error = $dataService->getLastError();
    if ($error != null) {
        echo "The Status code is: " . $error->getHttpStatusCode() . "\n";
        echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
        echo "The Response message is: " . $error->getResponseBody() . "\n";
        echo "The Intuit Helper message is: IntuitErrorType:{" . $error->getIntuitErrorType() . "} 
            IntuitErrorCode:{" . $error->getIntuitErrorCode() . "} 
            IntuitErrorMessage:{" . $error->getIntuitErrorMessage() . "} 
            IntuitErrorDetail:{" . $error->getIntuitErrorDetail() . "}";
    } 
    

    For a complete example, see TestYourOAuth1Settings in the _Samples directory.

    Configuring the SDK settings

    The PHP SDK is configured with default values for settings such as minor version, number of retries, and logging. You can override these default settings by either editing the configuration file or setting the properties of the IppConfiguration object in your code. For details on how to configure the settings, see Configuration.

    Configure an SPL autoloader

    To use the Composer library, configure an SPL autoloader by entering the following as the first line in your PHP script before calling other libraries or classes:

    require "vendor/autoload.php";

    You can declare your own SPL autoloader; however, using Composer’s vendor/autoload.php hook is recommended.

    Declare the DataService class

    To use the PHP SDK, the following class is required:

    use QuickBooksOnline\API\DataService\DataService;

    Include this in the script before making an HTTP call.

    Using the Class Library

    Classes provided in the PHP Class Library correspond to the QuickBooks API resources. The Class Library provides wrappers for calling QuickBooks API resources.

    Making QuickBooks API calls

    The SDK provides wrappers for calling QuickBooks API resources. See the PHP class library for reference information. For creating or updating most resources, the SDK also provides facade classes, which allow you to pass parameters in an array. For details on using the facade classes, see Creating and updating resources below. You can use either the wrapper classes or facade classes to create or update resources, but the facade classes allow you to take advantage of PHP arrays.

    Using the RequestId parameter

    The requestId parameter uniquely identifies the HTTP request sent from the app to the service. The following is an example of a basic call for a requestId:

    $url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . ‘RequestID=‘ . ‘(unique string)’
    

    Wherever you make a new API call, you must get a new requestId for that call. For details on the requestId parameter, see REST API quick reference. For additional useful information, see Request ID update for QuickBooks Online integration.

    Creating and updating resources

    Beginning with PHP SDK 3.2.0, facade classes are available to create and update objects from an array for the following entities:

    • Account
    • Bill
    • BillPayment
    • Class
    • CompanyCurrency
    • CreditMemo
    • Customer
    • Department
    • Deposit
    • Employee
    • Estimate
    • Invoice
    • Item
    • JournalEntry
    • Line*
    • Payment
    • Purchase
    • PurchaseOrder
    • RefundReceipt
    • SalesReceipt
    • TaxSerivce and TaxRate (for create only)
    • TimeActivity
    • Transfer
    • Vendor
    • VendorCredit

    *The Line class is provided as an easy way to construct Line items for high usage of Line objects. Line is not a QuickBooks Online API endpoint entity.

    To use the create and update methods for these entities, first import the corresponding facade class:

    use QuickBooksOnline\API\Facades\{Facade_Class_Name};

    You can then use the static class to create or update corresponding objects. The array corresponds to the JSON parameters described in the Accounting API Reference. For example, the following example creates an invoice using parameters described in the API Accounting Reference for Invoice:

    $myInvoiceObj = Invoice::create([
      "DocNumber" => "1070",
      "LinkedTxn" => [],
      "Line" => [[
          "Id" => "1",
          "LineNum" => 1,
          "Amount" => 150.0,
          "DetailType" => "SalesItemLineDetail",
          "SalesItemLineDetail" => [
              "ItemRef" => [
                  "value" => "1",
                  "name" => "Services"
              ],
              "TaxCodeRef" => [
                  "value" => "NON"
              ]
          ]
      ], [
          "Amount" => 150.0,
          "DetailType" => "SubTotalLineDetail",
          "SubTotalLineDetail" => []
      ]],
      "CustomerRef" => [
          "value" => "1",
          "name" => "Amy's Bird Sanctuary"
      ]
    ]);
    $resultingInvoiceObj = $dataService->Add($myInvoiceObj);

    The following sample updates an invoice:

    $updatedInvoice = Invoice::update($myInvoiceObj, [
        "sparse" => true,
        "Deposit" => 100000,
        "DocNumber" => "12223322"
    ]);
    $resultingUpdatedInvoiceObj = $dataService->Add($updatedInvoice);

    Passing objects in the array

    The facade class members can accept objects as references in the array. For example, when creating multiple lines within the Line facade, you can easily pass it to the Invoice facade to create an invoice:

     <?php
     for($i = 1; $i<= 3; $i ++){
        $LineObj = Line::create([
            "Id" => $i,
            "LineNum" => $i,
            "Description" => "Pest Control Services",
            "Amount" => 35.0,
            "DetailType" => "SalesItemLineDetail",
            "SalesItemLineDetail" => [
                "ItemRef" => [
                    "value" => "1",
                    "name" => "Pest Control"
                ],
                "UnitPrice" => 35,
                "Qty" => 1,
                "TaxCodeRef" => [
                    "value" => "NON"
                ]
            ]
        ]);
        $lineArray[] = $LineObj;
     }
     
     //Add a new Invoice
     $theResourceObj = Invoice::create([
          "Line" =>  $lineArray,
         "CustomerRef"=> [
          "value"=> "1"
          ],
           "BillEmail" => [
                 "Address" => "Familiystore@intuit.com"
           ],
           "BillEmailCc" => [
                 "Address" => "a@intuit.com"
           ],
           "BillEmailBcc" => [
                 "Address" => "v@intuit.com"
           ]
     ]);
     ?>

    Creating resources

    The following example shows how to import the facade class and create a more detailed invoice:

    ?php
    
    //Replace the line with require "vendor/autoload.php" if you are using the Samples from outside of _Samples folder
    include('../config.php');
    use QuickBooksOnline\API\Core\ServiceContext;
    use QuickBooksOnline\API\DataService\DataService;
    use QuickBooksOnline\API\PlatformService\PlatformService;
    use QuickBooksOnline\API\Core\Http\Serialization\XmlObjectSerializer;
    use QuickBooksOnline\API\Facades\Invoice;
    use QuickBooksOnline\API\Facades\Line;
    
    // Prep Data Services
    $dataService = DataService::Configure(array(
           'auth_mode' => 'oauth1',
             'consumerKey' => "lve2eZN6ZNBrjN0Wp26JVYJbsOOFbF",
             'consumerSecret' => "fUhPIeu6jrq1UmNGXSMsIsl0JaHuHzSkFf3tsmrW",
             'accessTokenKey' => "qye2etcpyquO3B1t8ydZJI8OTelqJCMiLZlY5LdX7qZunwoo",
             'accessTokenSecret' => "2lEUtSEIvXf64CEkMLaGDK5rCwaxE9UvfW1dYrrH",
             'QBORealmID' => "193514489870599",
             'baseUrl' => "https://qbonline-e2e.api.intuit.com/"
    ));
    $dataService->setLogLocation("/Users/hlu2/Desktop/newFolderForLog");
    $dataService->setMinorVersion("8");
    $lineArray = array();
    
    // Create three Lines
    $i = 0;
    for($i = 1; $i<= 3; $i ++){
       $LineObj = Line::create([
           "Id" => $i,
           "LineNum" => $i,
           "Description" => "Pest Control Services",
           "Amount" => 35.0,
           "DetailType" => "SalesItemLineDetail",
           "SalesItemLineDetail" => [
               "ItemRef" => [
                   "value" => "1",
                   "name" => "Pest Control"
               ],
               "UnitPrice" => 35,
               "Qty" => 1,
               "TaxCodeRef" => [
                   "value" => "NON"
               ]
           ]
       ]);
       $lineArray[] = $LineObj;
    }
    
    // Add a new invoice
    $theResourceObj = Invoice::create([
         "Line" =>  $lineArray,
        "CustomerRef"=> [
         "value"=> "1"
         ],
          "BillEmail" => [
                "Address" => "Familiystore@intuit.com"
          ],
          "BillEmailCc" => [
                "Address" => "a@intuit.com"
          ],
          "BillEmailBcc" => [
                "Address" => "v@intuit.com"
          ]
    ]);
    $resultingObj = $dataService->Add($theResourceObj);
    $error = $dataService->getLastError();
    if ($error != null) {
        echo "The Status code is: " . $error->getHttpStatusCode() . "\n";
        echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
        echo "The Response message is: " . $error->getResponseBody() . "\n";
    }
    else {
        echo "Created Id={$resultingObj->Id}. Reconstructed response body:\n\n";
        $xmlBody = XmlObjectSerializer::getPostXmlFromArbitraryEntity($resultingObj, $urlResource);
        echo $xmlBody . "\n";
    }
    
    /*
    Created Customer Id=801. Reconstructed response body:
    <?xml version="1.0" encoding="UTF-8"?>
    <ns0:Customer xmlns:ns0="http://schema.intuit.com/finance/v3">
      <ns0:Id>801</ns0:Id>
      <ns0:SyncToken>0</ns0:SyncToken>
      <ns0:MetaData>
        <ns0:CreateTime>2013-08-05T07:41:45-07:00</ns0:CreateTime>
        <ns0:LastUpdatedTime>2013-08-05T07:41:45-07:00</ns0:LastUpdatedTime>
      </ns0:MetaData>
      <ns0:GivenName>GivenName21574516</ns0:GivenName>
      <ns0:FullyQualifiedName>GivenName21574516</ns0:FullyQualifiedName>
      <ns0:CompanyName>CompanyName426009111</ns0:CompanyName>
      <ns0:DisplayName>GivenName21574516</ns0:DisplayName>
      <ns0:PrintOnCheckName>CompanyName426009111</ns0:PrintOnCheckName>
      <ns0:Active>true</ns0:Active>
      <ns0:Taxable>true</ns0:Taxable>
      <ns0:Job>false</ns0:Job>
      <ns0:BillWithParent>false</ns0:BillWithParent>
      <ns0:Balance>0</ns0:Balance>
      <ns0:BalanceWithJobs>0</ns0:BalanceWithJobs>
      <ns0:PreferredDeliveryMethod>Print</ns0:PreferredDeliveryMethod>
    </ns0:Customer>
    */

    For entities that are not included in the above list, create objects as described in the CRUD sample app.

    Updating resources

    To update a single resource, import the corresponding facade class, read the resource, and then update it. The following example updates an invoice with new content:

    <?php
    require "vendor/autoload.php";
    use QuickBooksOnline\API\DataService\DataService;
    use QuickBooksOnline\API\Facades\Invoice;
    use QuickBooksOnline\API\Core\Http\Serialization\XmlObjectSerializer;
    
    $dataService = DataService::Configure(array(
             'auth_mode' => 'oauth2',
    'consumerKey' => "qyprdUSoVpIHrtBp0eDMTHGz8UXuSz",
    'consumerSecret' => "TKKBfdlU1I1GEqB9P3AZlybdC8YxW5qFSbuShkG7",
    'accessTokenKey' => "lvprdzNckPXUquNnptGJXw84tgnAUQ7HQw9j7vbZdJQmc2Wj",
    'accessTokenSecret' => "qSmQj5RLl0jA4HRvova3xwmZwRMclQcsNLU1XwXO",
    'QBORealmID' => "193514464689044",
    'baseUrl' => "https://sandbox-quickbooks.api.intuit.com/"
    ));
    $dataService->setLogLocation("/Users/hlu2/Desktop/newFolderForLog");
    
    $entities = $dataService->Query("select * from Invoice where docNumber='1566'");
    $error = $dataService->getLastError();
    if ($error != null) {
        echo "The Status code is: " . $error->getHttpStatusCode() . "\n";
        echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
        echo "The Response message is: " . $error->getResponseBody() . "\n";
        exit();
    }
    if(!empty($entities) && sizeof($entities) == 1){
        $theInvoice = current($entities);
        $updatedInvoice = Invoice::update($theInvoice, [
             'sparse' => true,
             'DocNumber' => '8999'
        ]);
        $dataService->add($updatedInvoice);  
    }
    ?>
    Full vs sparse updates

    QuickBooks Online provides two update types: full or sparse. The sparse update operation updates a subset of attributes for a given object—only those attributes specified in the request are updated. Missing attributes are left unchanged. For a full update operation, elements missing from the request are cleared.

    The following are considerations for using a sparse update:

    • Prevent unintended overwrites: A client application often does not use all the fields of an entity, so when it sends a full update request with only fields they use, it results in an erroneous blanking out of fields that were not sent.
    • Reduce request payload: Always desired, but this consideration is more relevant when the client application is mobile because of lower speeds, spotty connections, and the fact that mobile users are sensitive to data usage in each billing cycle.
    • Facilitate future field additions: New fields can be added to an entity without past versions of production applications clearing all other existing fields inadvertently, as would happen with a full update operation.

    Deleting resources

    To delete a single resource, call the delete method on the dataService object. The following example deletes an object:

    //Same as constructing the DataService
    ...
    $targetInvoiceObj = $dataService->FindById("The ID of the Invoice");
    $currentResultObj = $dataService->Delete($targetObject);
    if ($crudResultObj)
        echo "Delete the purchase object that we just created.\n";
    else
        echo "Did not delete the purchase object that we just created.\n";
    

    Querying resources

    To use query a resource, construct the query string and call the $dataService->Query() method. The following example shows how to query all invoices:

    //Same for constructing the DataService object
    ...
    $allInvoices = $dataServices->Query("SELECT * FROM Invoice"); 

    The query statement is very similar to an SQL query. For valid keywords, such as filterable or sortable, that can be included in a query, see the QuickBooks Accounting API reference for the specific entity. For example, the following example matches an invoice with a specific docNumber:

    $theInvoice = $dataServices->Query("select * from Invoice where docNumber='1038'");

    SQL comparison values in the query must be delimited using single quotation marks. Comparison values that are delimited with double quotes as shown below, or have no delimiters, are invalid:

    // This query generates a 400 error, error parsing string
    $theInvoice = $dataServices->Query("select * from Invoice where docNumber=1038");

    When querying a ReferenceType (which ends with "Ref"), do not use TypeRef.value format; instead use TypeRef. For example, to query invoices from a customer with Customer ID 58, you would use the following:

    SELECT * FROM Invoice WHERE CustomerRef='58' 

    Paginating query results

    To implement pagination, include the pagination parameters in the query. To page through the results, specify STARTPOSITION (position of the entity in the query results) and MAXRESULTS (maximum number of entities in the result) as shown in the following example:

    $entities = $dataService->Query("SELECT * FROM Invoice STARTPOSITION 1 MAXRESULTS 10");

    For more information, see Data queries.

    Handling errors and timeouts

    For whatever reason, the HTTP requests at the heart of the API may not always succeed. Every method will return false if an error occurred, and you should always check for this before acting on the results of the method call.

    $resultingCustomerObj = $dataService->Add($customerObj);
    $error = $dataService->getLastError();
    if ($error != null) {
        echo "The Status code is: " . $error->getHttpStatusCode() . "\n";
        echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
        echo "The Response message is: " . $error->getResponseBody() . "\n";
    }
    else {
        # code...
        // Echo some formatted output
        echo "Created Customer Id={$resultingCustomerObj->Id}. Reconstructed response body:\n\n";
        $xmlBody = XmlObjectSerializer::getPostXmlFromArbitraryEntity($resultingCustomerObj, $urlResource);
        echo $xmlBody . "\n";
    }

    Generating reports

    To generate reports, create a ReportService object. For more about generating reports, see Reports.

    Creating and reading a TaxCode

    To create a TaxCode object, use GlobalTaxService. For more information, see Manage tax for US locales or Manage tax for non-US locales.

    Attachments

    A file, such as a receipt image, product photo, or note, can be linked to a transaction or Item object. For details about attachments, see Attachments.

     Got Questions? Get Answers in our developer forums.