Getting started:



Lets assume you want to use this LibreOffice/OpenOffice document as your template.

API-Example: Generating a pdf from a template

  • Send your data via http POST request.
    
    The url:
    
    http://template2pdf.com/jobs.json
    
    Make sure that you send the following header information:
    
    Accept: application/json
    
    POST fields-payload:
    
    {'api_key'=>'<API_KEY>',
     'ootemplate[attachment]'=>'@file',
     'data'=> hash_with_key_values_to_search_and_replace}
    
    Example:
    #
    # api_key:          
    #
     {'api_key' => '<API_KEY>',   
    #
    # your template to upload:
     'ootemplate[attachment]'=>'@file',
    #
    #
    # the key values in the 'data' section will be used for the substitution inside the template
    # for example: if your template contains [[example]], it will be replaced with 'test123'
    #
      'data'=>{'key'=>'value',
                 'example'=>'test123',
                 ...},
    #
    # 'list_keys' are used to define lists that need to get into the template. 
    # Think of invoice items as an example.
    # Here you see 'list_key_item' pointing to an array of key-value-hashes
    # Inside your template you can use '[[list_key_item]]' to indicate that you want to build a list.
    # Once the program sees a list key inside a table-row, it knows that this row is subject to be expanded to a list.
    # Please see the example invoice and how [[list_key_item]] is used in there.
    # Be aware that there is no limitation on 'list_key_name'. You can generate as many lists as you want.
    # 
    'data'=>  {'key'=>'value',
               'example'=>'test123',
               'list_key_item'=>[{"item_quantity"=>"2","item_amount"=>"90,00 USD",...},
                              {"item_quantity"=>"1","item_amount"=>"49,99 USD",...},
                              {"item_quantity"=>"1","item_amount"=>"8,98 USD",...}]
              }
    
     
    
    
    On success, the server will return with HTTP STATUS CODE 201 (create).
    On error, the server will return an error description in the body.
                      
    
    If you receive a 201 response to your request, parse the returned headers for the 'Location'.
    Wait a few seconds, to give the pdf-generator a bit time to run.
    Then issue a normal HTTP GET request to that location.
    If it returns with HTTP STATUS CODE 200, save to body as pdf file.
    If the pdf is not yet ready, the system will return with a HTTP STATUS CODE 503 and ask you to refresh the resource.
    If there was an error during pdf creation, you will get an HTTP STATUS CODE 4XX/5XX (except 503) with an explanation of the error inside the body.                  
                    
  • download odt2pdf.html

    Invoice Id
    Invoice Date
    User Company
    User Salut
    User Firstname
    User Lastname
    User Street
    User City
    User Zip
    User Country
    Sales Name
    Sales Email
    Amount Total
    Amount Tax
    Tax
    Freetext
    Template-File
    NumberTitleAmountQuantityAmount Total
    Api-Key:

    Invoice Id
    Invoice Date
    User Company
    User Salut
    User Firstname
    User Lastname
    User Street
    User City
    User Zip
    User Country
    Sales Name
    Sales Email
    Amount Total
    Amount Tax
    Tax
    Freetext
    Template-File
    NumberTitleAmountQuantityAmount Total
    Api-Key:
  • download odt2pdf.bash

    # this does the following:
    # submit the data and template for the job
    # get the location where the pdf file will be from the 'Location' part of the returned header
    # wait some seconds to be sure that the file is generated 
    # (if not you need to follow redirects until it appears)
    # and then download the pdf
    url=$(curl -i -F "ootemplate[attachment]=@example_invoice_template.odt;type=application/vnd.oasis.opendocument.text" \
            -H "Accept: application/json" \
            -X POST \
            -F 'api_key=<API_KEY>'\
            -F 'data[invoice_id]=12345'\
            -F 'data[invoice_date]=31.02.2050'\
            -F 'data[user_company_name]=Taco-Tools'\
            -F 'data[user_salut]=Mr'\
            -F 'data[user_first]=Larry'\
            -F 'data[user_last]=Hickup'\
            -F 'data[user_street]=Examplestreet'\
            -F 'data[user_city]=Crazytown'\
            -F 'data[user_zip]=54321'\
            -F 'data[user_country]=Flatland'\
            -F 'data[sales_name]=Sven'\
            -F 'data[sales_email]=sven@test.com'\
            -F 'data[amount_total]=$64.00'\
            -F 'data[amount_tax]=$0.00'\
            -F 'data[tax]=0%'\
            -F 'data[freetext]=no comment'\
            -F 'data[list_key_item][][item_no]=482'\
            -F 'data[list_key_item][][item_quantity]=2'\
            -F 'data[list_key_item][][item_amount]=$30.00'\
            -F 'data[list_key_item][][item_amount_total]=$60.00'\
            -F 'data[list_key_item][][item_title]=Tacos'\
            -F 'data[list_key_item][][item_no]=692'\
            -F 'data[list_key_item][][item_quantity]=1'\
            -F 'data[list_key_item][][item_amount]=$4.00'\
            -F 'data[list_key_item][][item_amount_total]=$4.00'\
            -F 'data[list_key_item][][item_title]=Taco-Adapter'\
            "http://template2pdf.com/jobs.json" |grep Location|sed 's/Location://g'|sed 's/\r//g'); \
            sleep 3; \
            curl -L --retry 10 $url > example_output.pdf;
    
                    
  • download odt2pdf.php

    array(       array("no"=>'482',"quantity"=>"2","amount"=>"$30,00","amount_total"=>"$60.00","title"=>"Tacos"),
                                          array("no"=>'692',"quantity"=>"1","amount"=>"$4.00","amount_total"=>"4.00","title"=>"Taco-Adapter")));
    
    # Usage:
      $t2p = new Template2PdfSimple($api_location,$api_key);
      $t2p->enable_debug();
      $t2p->convert($input_filename,$output_filename,$normal_key_values,$lists);
    
    
    */
    
    class Template2PdfSimple{
    
      public function Template2PdfSimple($api_location,$api_key) {
        $this->api_location = $api_location;
        $this->api_key = $api_key;
        $this->debug = false;
      }
    
      public function enable_debug(){
        $this->debug = true;
      }
      
      private function dprint($x){
        if($this->debug){
          print($x);
        }
      }
    
      public function convert($input_filename,$output_filename,$normal_key_values,$lists){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,$this->api_location.'jobs.json');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json',"Content-type: multipart/form-data"));
        $big_hash = $this->build_fields($input_filename,$normal_key_values,$lists);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $big_hash);
        $response=curl_exec ($ch);
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);
        $body = substr($response, $header_size);
        $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
        if ($httpCode == 201) {
          $location = '';
          $parts = explode("\r\n",$header);
          foreach($parts as $part){
            if(preg_match('/Location\:/',$part)){
              $location = trim(str_replace('Location: ','',$part));
            }
          }
          if ($location != ''){
            $this->dprint("found location\n");
            for($i=0;$i<10;$i++){
              $this->dprint("try fetch #".$i."\n");
              $return_code = $this->fetch_pdf($location);
              if($return_code == 200){
                break;
              }
              sleep(1+($i*$i*$i));
            }
            if($return_code == 200){
              $this->dprint("example_output.pdf created\n");         
            } else if($return_code == 503){
              $this->dprint("\n");
              $this->dprint("Document is not yet ready. Please try to reload in a few minutes:\n");
              $this->dprint($location);
              $this->dprint("\n");
            } else {
              $this->dprint("\nAn error occured.\nCode: ".$return_code."\n");
            }
          }
        } else {
          $this->dprint("\nAn error occured.\nCode: ".$httpCode."\n");
          $this->dprint(print_r($response."\n\n"));
        }
        
      }
    
    
      private function fetch_pdf($url){
        $saveto = './example_output.pdf';
        $ch = curl_init ($url);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
        $raw=curl_exec($ch);
        $httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close ($ch);
        if ($httpCode == 200){
        if(file_exists($saveto)){
            unlink($saveto);
        }
        $fp = fopen($saveto,'x');
        fwrite($fp, $raw);
        fclose($fp);
        }
        return $httpCode;
      } 
    
      private  function build_fields($input_filename,$normal_key_values,$lists){
        $big_hash = array('api_key'=> $this->api_key,
                          "ootemplate[attachment]" => "@".realpath($input_filename).";type=application/vnd.oasis.opendocument.text");
        foreach($normal_key_values as $key => $value){
          $big_hash['data['.$key.']'] = $value;
        }
        foreach($lists as $list_key => $rows){
          foreach($rows as $key => $value_rows){
            foreach($value_rows as $lkey => $value){
            $big_hash['data[list_key_'.$list_key.'['.$key.']]['.$list_key.'_'.$lkey.']'] = $value;
            }
          }
        }
        return $big_hash;    
      }
    
    
      public static function base64_image($filename){
        return base64_encode(file_get_contents($filename));
      }
    
    }
    
    
      $api_location = "http://template2pdf.com/";
      $api_key = "<API_KEY>";
      $input_filename = "./example_invoice_template.odt";
      $output_filename = './example_output.pdf';
      $normal_key_values = array('invoice_id'=>'12345',
                                  'invoice_date'=>'31.02.2050',
                                  'user_company_name'=>'Taco-Tools',
                                  'user_salut'=>'Mr',
                                  'user_first'=>'Larry',
                                  'user_last'=>'Hickup',
                                  'user_street'=>'Examplestreet',
                                  'user_city'=>'Crazytown',
                                  'user_zip'=>'54321',
                                  'user_country'=>'Flatland',
                                  'sales_name'=>'Sven',
                                  'sales_email'=>'sven@test.com',
                                  'amount_total'=>'$64.00',
                                  'amount_tax'=>'$0.00',
                                  'tax'=>'0%',
                                  'freetext'=>'no comment');
      $lists = array('item'=>array(       array("no"=>'482',"quantity"=>"2","amount"=>"$30,00","amount_total"=>"$60.00","title"=>"Tacos"),
                                          array("no"=>'692',"quantity"=>"1","amount"=>"$4.00","amount_total"=>"4.00","title"=>"Taco-Adapter")));
    
      $t2p = new Template2PdfSimple($api_location,$api_key);
      $t2p->enable_debug();
      $t2p->convert($input_filename,$output_filename,$normal_key_values,$lists);
                
    ?>
    
                    
  • download odt2pdf.rb

    #! /usr/bin/ruby
    
    ## Example usage of template2pdf api:
    ## Basic configuration
    #  api_location = "http://template2pdf.com/"
    #  api_key = "your_api_key"
    #  input_filename = "example_invoice_template.odt"
    #  output_filename = './example_output.pdf'
    #  normal_key_values = { 'name'=>'Sven',
    #                        'email'=>'sven@beastiebytes.com',
    #                        'amount_total'=>'234.23 USD',
    #                        'amount_tax'=>'0%',
    #                        'pay_day'=>'today',
    #                        'freetext'=>'no comment',
    #                        'invoice_id'=>'2342',
    #                        'invoice_date'=>'xmas',
    #                        'user_name'=>'Jane Doe',
    #                        'user_street'=>'Mainstreet',
    #                        'user_city'=>'Berlin'}
    #  lists = { 'item'=>[ {'no'=>'482','title'=>'Tacos','amount'=>'$30.00','quantity'=>'2','amount_total'=>'$60.00'},
    #                      {'no'=>'692','title'=>'Taco-Adapter','amount'=>'$4.00','quantity'=>'1','amount_total'=>'$4.00'}],
    #            'otherlist'=>[ {'whatever'=>'product1','amount'=>'2'},
    #                      {'whatever'=>'product2','amount'=>'4'}]}
    #
    ## Usage:
    # t2p = Template2PdfSimple.new(api_location,api_key)
    # t2p.convert(input_filename,output_filename,normal_key_values,lists)
    
    
    require 'rubygems'
    require 'curb'
    require 'json'
    require "base64"
    
    
    class Template2PdfSimple
    
      def initialize(api_location,api_key)
        @api_location = api_location
        @api_key = api_key
        @debug = true
      end
      
      def enable_debug
        @debug = true
      end
      
      def dputs(*args)
        puts args if @debug
      end
     
      def convert(input_filename,output_filename,normal_key_values,lists)
        fields = build_fields(input_filename,normal_key_values,lists)
    
        c = Curl::Easy.http_post("#{@api_location}jobs.json",fields) do |curl|
          curl.headers['Accept'] = 'application/json'
          curl.multipart_form_post = true
          #curl.ssl_verify_peer = false
          #curl.ssl_verify_host = false
        end
      
        if c.response_code.to_i == 201
          http_response, *http_headers = c.header_str.split(/[\r\n]+/).map(&:strip)
          http_headers = Hash[http_headers.flat_map{ |s| s.scan(/^(\S+): (.+)/) }]
          new_location_url = http_headers["Location"]
          dputs "job created"
          dputs "sleeping 2 seconds to give converter enough time"
          sleep 2
          dputs "trying to fetch pdf"
          res = 0
          10.times do |i|
            dputs "try: #"+i.to_s
            res = fetchit(new_location_url,output_filename)
            break if res == 200 # finish on success
            break unless res == 503 # continue on redirects
            sleep 1+(i*i*i);
          end
          
          if res == 200
            dputs "example_output.pdf created"
          elsif res == 503
            dputs ""
            dputs "Document is not yet ready. Please try to reload in a few minutes:"
            dputs new_location_url
            dputs ""
          else
            dputs "\nAn error occured.\nCode: "+res+"\n";
          end
        elsif c.response_code.to_i == 401
          dputs "Authentication error. Please check your API key.\n";
        else
          dputs "\nAn error occured.\nCode: "+c.response_code.to_s+"\n";
          dputs c.body_str.to_s+"\n\n"
        end
         
      end
    
    
    
      def fetchit(new_location_url,output_filename)
        dputs new_location_url
        dputs "" 
        c = Curl::Easy.http_get(new_location_url) do |curl|
          curl.follow_location=true
          curl.max_redirects = 20
          #curl.ssl_verify_peer = false
          #curl.ssl_verify_host = false
        end
        if c.response_code.to_i == 200
          File.open(output_filename, "wb") do |file|
            file.write(c.body_str)
          end
        end
        return c.response_code.to_i
      end
    
      def build_fields(input_filename,normal_key_values,lists)
        attachment_field = Curl::PostField.file('ootemplate[attachment]', input_filename)
        attachment_field.content_type= "application/vnd.oasis.opendocument.text"
        fields = [attachment_field]
        fields << Curl::PostField.content('api_key',@api_key)
        normal_key_values.each do |k,v|
          fields << Curl::PostField.content('data['+k.to_s+']',v)
        end
        lists.each do |list_key,collection|
          collection.each do |row|
            row.each do |k,v|
              fields <<  Curl::PostField.content('data[list_key_'+list_key+'][]['+list_key+'_'+k+']',v)
            end
          end
        end
        fields
      end
    
      def self.base64_image(filename)
        Base64.strict_encode64(File.open(filename, "rb").read)
      end
    
    
    end
    
      api_location = "http://template2pdf.com/"
      api_key = "<API_KEY>"
      input_filename = "example_invoice_template.odt"
      output_filename = './example_output.pdf'
      normal_key_values = { 'invoice_id'=>'12345',
                            'invoice_date'=>'31.02.2050',
                            'user_company_name'=>'Taco-Tools',
                            'user_salut'=>'Mr',
                            'user_first'=>'Larry',
                            'user_last'=>'Hickup',
                            'user_street'=>'Examplestreet',
                            'user_city'=>'Crazytown',
                            'user_zip'=>'54321',
                            'user_country'=>'Flatland',
                            'sales_name'=>'Sven',
                            'sales_email'=>'sven@test.com',
                            'amount_total'=>'$64.00',
                            'amount_tax'=>'$0.00',
                            'tax'=>'0%',
                            'freetext'=>'no comment'}
      lists = { 'item'=>[ {'no'=>'482','title'=>'Tacos','amount'=>'$30.00','quantity'=>'2','amount_total'=>'$60.00'},
                          {'no'=>'692','title'=>'Taco-Adapter','amount'=>'$4.00','quantity'=>'1','amount_total'=>'$4.00'}]}
    
    t2p = Template2PdfSimple.new(api_location,api_key)
    t2p.enable_debug
    t2p.convert(input_filename,output_filename,normal_key_values,lists)
    
    
    
    
    
    
    
                    
  • download odt2pdf.py

    #! /usr/bin/env python
    import pycurl
    import StringIO
    import simplejson
    import time
    import sys
    import re
     
     
    # run this in a loop until pdf is ready
    def fetchit(new_location_url):
      print new_location_url
      print "" 
      curl = pycurl.Curl()
      buff = StringIO.StringIO()
      curl.setopt(pycurl.URL, new_location_url)
      curl.setopt(pycurl.WRITEFUNCTION, buff.write)
      curl.setopt(pycurl.FOLLOWLOCATION, 1)
      #curl.setopt(pycurl.SSL_VERIFYHOST, 0)
      #curl.setopt(pycurl.SSL_VERIFYPEER, 0)
    
    
      curl.perform()
      if curl.getinfo(pycurl.HTTP_CODE)==200:
        pdffile = open("example_output.pdf", "wb")
        pdffile.write(buff.getvalue())
        pdffile.close()
      return curl.getinfo(pycurl.HTTP_CODE)
     
    class Storage:
        def __init__(self):
            self.contents = ''
        def store(self, buf):
            self.contents += buf
        def __str__(self):
            return self.contents
     
    
    c = pycurl.Curl()
    b = StringIO.StringIO()
    retrieved_headers = Storage()
    c.setopt(pycurl.HTTPHEADER, ['Accept: application/json',"Content-Type: multipart/form-data"])
    c.setopt(pycurl.POST, 1)
    c.setopt(c.HTTPPOST, [("ootemplate[attachment]", (c.FORM_FILE, "./example_invoice_template.odt",c.FORM_CONTENTTYPE, "application/vnd.oasis.opendocument.text")),
                          ('api_key','<API_KEY>'),
                          ('data[invoice_id]','12345'),
                          ('data[invoice_date]','31.02.2050'),
                          ('data[user_company_name]','Taco-Tools'),
                          ('data[user_salut]','Mr'),
                          ('data[user_first]','Larry'),
                          ('data[user_last]','Hickup'),
                          ('data[user_street]','Examplestreet'),
                          ('data[user_city]','Crazytown'),
                          ('data[user_zip]','54321'),
                          ('data[user_country]','Flatland'),
                          ('data[sales_name]','Sven'),
                          ('data[sales_email]','sven@test.com'),
                          ('data[amount_total]','$64.00'),
                          ('data[amount_tax]','$0.00'),
                          ('data[tax]','0%'),
                          ('data[freetext]','no comment'),
                          ('data[list_key_item][0][item_no]','482'),
                          ('data[list_key_item][0][item_quantity]','2'),
                          ('data[list_key_item][0][item_amount]','$30.00'),
                          ('data[list_key_item][0][item_amount_total]','$60.00'),
                          ('data[list_key_item][0][item_title]','Tacos'),
                          ('data[list_key_item][1][item_no]','692'),
                          ('data[list_key_item][1][item_quantity]','1'),
                          ('data[list_key_item][1][item_amount]','$4.00'),
                          ('data[list_key_item][1][item_amount_total]','$4.00'),
                          ('data[list_key_item][1][item_title]','Taco-Adapter')
                          ])
    
    c.setopt(c.URL, 'http://template2pdf.com/jobs.json')
    c.setopt(c.HEADERFUNCTION, retrieved_headers.store)
    c.setopt(pycurl.WRITEFUNCTION, b.write)
    #c.setopt(pycurl.SSL_VERIFYHOST, 0)
    #c.setopt(pycurl.SSL_VERIFYPEER, 0)
    c.perform()
    result = b.getvalue()
    listing = str(retrieved_headers).split("\r\n")
    location = ''
    # extract location out of header:
    for header_element in listing:
      if re.match('Location:',header_element):
        location = header_element.split('Location: ')[1].strip()
     
    # check if job started
    if c.getinfo(pycurl.HTTP_CODE)==201:
      print "job created"
      print "sleeping 2 seconds to give converter enough time"
      time.sleep(2)
      print "trying to fetch pdf"
      res = 0
      # try 10 times to load the pdf
      for i in range(10): # or xrange if you are on 2.X
        print "try: #"+str(i)
        res = fetchit(location)
        if res == 200: # finish on success
          break
        if res != 503:
          break  # continue on redirects
        time.sleep (1+(i*i*i));
     
      # nice output to know what happened:
      if res == 200:
        print "example_output.pdf created"
      elif res == 503:
        print ""
        print "Document is not yet ready. Please try to reload in a few minutes:"
        print new_location_url
        print ""
      else:
        print "\nAn error occured.\nCode: "+str(res)+"\n";
     
    else:
      print "\nAn error occured.\nCode: "+str(c.getinfo(pycurl.HTTP_CODE))+"\n";
      print result+"\n\n"
     
    b.close()
    c.close() 
    
    
                    

If you followed the example, the API should return this pdf