Download HelloSign Documents using Laravel
Tags: hellosign, laravel, tutorial
Published: 2022-10-09 05:40:23

Ever need to download all HelloSign documents with Laravel without the SDK? It can be done by basic HTTP requests with an API key generated by HelloSign.

## Things used
1. Laravel's built in HTTP Client (Guzzle)
2. Jobs to avoid HelloSign API rate limits
3. Functions will be placed in routes file instead of a controller (to prototype faster)

## Steps
1. Get API key from HelloSign

2. Add the api to the `.env` file
    ```
    HELLO_SIGN_API_KEY=
    ```

3. Create `hellosign.php` in the config folder
    ```php
    <?php
  
    return [
      'api_key' => env('HELLO_SIGN_API_KEY')
    ];
    ```

4. Create a migration `create_signature_requests_table` for the HelloSign document ids and add the following columns
    ```php
    $table->string('signature_request_id');
    $table->boolean('downloaded');
    ```

5. Create a model `SignatureRequest` and add the following
    ```php
    $table->string('signature_request_id');
    $table->boolean('downloaded');
    ```

6. Go to `routes/web.php` and add the following
    ```php
    use App\Jobs\DownloadJob;
  
    Route::get('/', function () {
      $api_key = config('hellosign.api_key');
  
      $page = 1;
      $total_pages = 99; // just a temporary high number
      
      while($page <= $total_pages) {
          // max out the per page and documents from all accounts
          $response = Http::get("https://{$api_key}:@api.hellosign.com/v3/signature_request/list?account_id=all&page_size=100&page={$page}");
  
          $object = $response->object();
  
          // set the number of total pages of documents
          if($page == 1) {
              $total_pages = $object->list_info->num_pages;
          }
  
          // loop through each result and get the signature_request_id if it exists
          foreach($object->signature_requests as $sig) {
              if(!isset($sig->signature_request_id)){
                  SignatureRequest::create(['signature_request_id' => $sig->signature_request_id]);
              }
          }
  
          // increase the page
          $page++;
      }
    });
  
    Route::get('download', function() {
      // get all signature ids that are not downloaded yet
      $sigs = SignatureRequest::where('downloaded', false)->get();
      
      // chunk it into 20, HelloSign API limits 25 requests per minute
      $chunks = $sigs->chunk(20);
      $chunks->all();
  
      // wait in minutes
      $wait = 0;
      foreach($chunks->all() as $chunk) {
          foreach($chunk as $sig) {
              // dispatch the download job and delay it by now + minutes
              dispatch(new DownloadJob($sig))->delay(now()->addMinutes($wait));
          }
          // increase wait time
          $wait++;
      }
    });
    ```



7. Create a job `DownloadJob` and update with the following
    ```php
    namespace App\Jobs;
    ...
    use Illuminate\Support\Facades\Http;
    use Illuminate\Support\Facades\Storage;
    use App\Models\SignatureRequest;
    
    ...
    public $sig;
  
      public function __construct(SignatureRequest $sig)
      {
          $this->sig = $sig;
      }
  
      public function handle()
      {
          $api_key = config('hellosign.api_key');
          
          // request the document
          $response = Http::get("https://{$api_key}:@api.hellosign.com/v3/signature_request/files/{$this->sig->signature_request_id}");
          
          // only download if response code is 200
          if($response->status() == 200) {
            // save the document into a `documents` folder in storage with the document id as it's file name
            Storage::put("documents/{$this->sig->signature_request_id}.pdf", $response->body() );
  
            // update db to downloaded
            $this->sig->downloaded = true;
            $this->sig->save();
          }
      }
    ```

8. Run the migrations with `php artisan migrate`
9. Start the queue with `php artisan queue:work`
10. Go to `localhost` in the browser to start getting the all the document ids
11. Once #10 is finished, in the browser go to `localhost/download` to add put the download into the queue
12. Wait until the queue is clean and go back to #11 to make sure it's finished (repeat as many times as needed)