Stripe direct integration
Stripe allows you to collect credit card payments for recurring or one-time payments.
Learn more about Stripe
In this guide:
How to send correct data to Octobat:
Integration requirements
The first thing that you have to do is tocreate an Octobat account.
Then, you have to own aStripe account.
To ensure that all your invoices are correctly generated, you must follow the way of this guide to make Stripe API calls.
Connect your Octobat and Stripe accounts

During your registration, you will be able to connect your Stripe account. At this moment, Octobat asks you read and write accesses to your Stripe account.
Testing
The best way for testing the Stripe integration with Octobat is to make API calls or create some objects within your Stripe dashboard and look what is happening on Octobat.
Collecting the customer's billing address
Octobat needs at least the billing country of your customer as an evidence in order to calculate the right tax rate.
(If your business is based in the US, Octobat also needs the billing postal code of your customer)
- In the front-end (token)
ViaStripe.js v3
// Handle form submission var form = document.getElementById('payment-form'); form.addEventListener('submit', function(event) { event.preventDefault(); var extraDetails = { name: form.querySelector('input[name=cardholder-name]').value, address_line1: form.querySelector('input[name=billing_address_line1]').value, address_line2: form.querySelector('input[name=billing_address_line2]').value, address_city: form.querySelector('input[name=billing_address_city]').value, address_state: form.querySelector('input[name=billing_address_state]').value, // State/County/Province/Region address_zip: form.querySelector('input[name=billing_address_zip]').value, // billing ZIP code as a string (e.g., "94301") address_country: form.querySelector('input[name=billing_address_country]').value // 2-letter ISO 3166-1 alpha-2 code }; stripe.createToken(card, extraDetails).then(function(result) { // handle result.error or result.token }); });
ViaStripe.js v2
Stripe.card.createToken({ number: $('.card-number').val(), cvc: $('.card-cvc').val(), exp_month: $('.card-expiry-month').val(), exp_year: $('.card-expiry-year').val(), name: $('.cardholder-name').val(), address_line1: $('.billing-address-line1').val(), address_line2: $('.billing-address-line2').val(), address_city: $('.billing-address-city').val(), address_state: $('.billing-address-state').val(), // State/County/Province/Region address_zip: $('.billing-address-zip').val(), // billing ZIP code as a string (e.g., "94301") address_country: $('.billing-address-country').val() // 2-letter ISO 3166-1 alpha-2 code }, stripeResponseHandler);
- In the back-end (API calls)
curl https://api.stripe.com/v1/customers \ -u sk_test_oCRWOhpjMI3qPvPoYYgbiWHI: \ -d description="John Doe" \ -d email="billing@johndoe.it" \ -d source=tok_h2mE320ZFnqlEf8abECRANpJ \ -d business_vat_id='IT01709820995' \ -d metadata[address_line1]='801 Via dei Condotti' \ -d metadata[address_line2]='Secondo piano' \ -d metadata[address_city]='Roma' \ -d metadata[address_state]='' \ -d metadata[address_zip]='10000' \ -d metadata[address_country]='IT' \ -d metadata[tax_number]='IT01709820995' \ -d metadata[business_type]='B2B'
customer = Stripe::Customer.create( :description => 'John Doe', :email => 'billing@johndoe.it', :source => params[:stripeToken], # Using Rails :business_vat_id => 'IT01709820995', # if valid, business type is B2B else B2C :metadata => { :address_line1 => '801 Via dei Condotti', :address_line2 => 'Secondo piano', :address_city => 'Roma', :address_state => '', # State/County/Province/Region :address_zip => '10000', # billing ZIP code as a string (e.g., "94301") :address_country => 'IT', # 2-letter ISO 3166-1 alpha-2 code :tax_number => 'IT01709820995', # can replace business_vat_id :business_type => 'B2B' # Force the customer business type even if the 'business_vat_id' is not valid } )
$customer = \Stripe\Customer::create(array( 'description' => 'John Doe', 'email' => 'billing@johndoe.it', 'source' => $_POST['stripeToken'], 'business_vat_id' => 'IT01709820995', // if valid, business type is B2B else B2C 'metadata' => array( 'address_line1' => '801 Via dei Condotti', 'address_line2' => 'Secondo piano', 'address_city' => 'Roma', 'address_state' => '', // State/County/Province/Region 'address_zip' => '10000', // billing ZIP code as a string (e.g., "94301") 'address_country' => 'IT', // 2-letter ISO 3166-1 alpha-2 code 'tax_number' => 'IT01709820995', // can replace business_vat_id 'business_type' => 'B2B' // Force the customer business type even if the 'business_vat_id' is not valid ) ));
customer = stripe.Customer.create( description="John Doe", email="billing@johndoe.it", source=request.form['stripeToken'], # Using Flask business_vat_id="IT01709820995", # if valid, business type is B2B else B2C metadata={ "address_line1": "801 Via dei Condotti", "address_line2": "Secondo piano", "address_city": "Roma", "address_state": "", # State/County/Province/Region "address_zip": "10000", # billing ZIP code as a string (e.g., "94301") "address_country": "IT", # 2-letter ISO 3166-1 alpha-2 code "tax_number": "IT01709820995", # can replace business_vat_id "business_type": "B2B", # Force the customer business type even if the 'business_vat_id' is not valid }, )
var stripe = require("stripe")( "sk_test_oCRWOhpjMI3qPvPoYYgbiWHI" ); stripe.customers.create({ description: 'John Doe', email: "billing@johndoe.it", source: request.body.stripeToken, // Using Express business_vat_id: "IT01709820995", // if valid, business type is B2B else B2C metadata: { address_line1: "801 Via dei Condotti", address_line2: "Secondo piano", address_city: "Roma", address_state: "", // State/County/Province/Region address_zip: "10000", // billing ZIP code as a string (e.g., "94301") address_country: "IT", // 2-letter ISO 3166-1 alpha-2 code tax_number: "IT01709820995", // can replace business_vat_id business_type: "B2B" // Force the customer business type even if the 'business_vat_id' is not valid } }, function(err, customer) { // asynchronously called });
VAT compliance data
That's better to send us the IP address of the customer as another piece of evidence (added to the customer's billing country and credit card country) in order to deduct the right location.
- Subscriptions
curl https://api.stripe.com/v1/subscriptions \ -u sk_test_oCRWOhpjMI3qPvPoYYgbiWHI: \ -d customer=cus_NO8K3C7wYRfSUv \ -d plan=basic-monthly \ -d metadata[ip_address]="90.90.71.253"
Stripe::Subscription.create( :customer => customer.id, :plan => "basic-monthly", :metadata => { :ip_address => request.remote_ip # An evidence of the customer's localization } )
\Stripe\Subscription::create(array( 'customer' => $customer->id, 'plan' => "basic-monthly", 'metadata' => array( 'ip_address' => $_SERVER['REMOTE_ADDR'] // An evidence of the customer's localization ) ));
import socket stripe.Subscription.create( customer=customer.id, plan="basic-monthly", metadata={ "ip_address": socket.gethostbyname(socket.gethostname()), # An evidence of the customer's localization }, )
var stripe = require("stripe")( "sk_test_oCRWOhpjMI3qPvPoYYgbiWHI" ); stripe.subscriptions.create({ customer: customer.id, plan: "basic-monthly", metadata: { ip_address: request.connection.remoteAddress // An evidence of the customer's localization } }, function(err, subscription) { // asynchronously called } );
charges attached to a customer curl https://api.stripe.com/v1/charges \ -u sk_test_oCRWOhpjMI3qPvPoYYgbiWHI: \ -d customer=cus_NO8K3C7wYRfSUv \ -d amount=999 \ -d currency=eur \ -d description="One-Time Charge" \ -d metadata[ip_address]="90.90.71.253"
Stripe::Charge.create( :customer => customer.id, :amount => 999, :description => 'One-Time Charge', :currency => 'eur', :metadata => { :ip_address => request.remote_ip # An evidence of the customer's localization } )
\Stripe\Charge::create(array( 'customer' => $customer->id, 'amount' => 999, 'description' => 'One-Time Charge', 'currency' => 'eur', 'metadata' => array( 'ip_address' => $_SERVER['REMOTE_ADDR'] // An evidence of the customer's localization ) ));
import socket stripe.Charge.create( customer=customer.id, amount=999, description="One-Time Charge", currency="eur", metadata={ "ip_address": socket.gethostbyname(socket.gethostname()), # An evidence of the customer's localization }, )
var stripe = require("stripe")( "sk_test_oCRWOhpjMI3qPvPoYYgbiWHI" ); stripe.charges.create({ customer: customer.id, amount: 999, description: "One-Time Charge", currency: "eur", metadata: { ip_address: request.connection.remoteAddress // An evidence of the customer's localization } }, function(err, charge) { // asynchronously called } );
- One-time charges without customer
curl https://api.stripe.com/v1/charges \ -u sk_test_oCRWOhpjMI3qPvPoYYgbiWHI: \ -d source=tok_189gLz2eZvKYlo2C8WdPMBzS \ -d receipt_email='billing@johndoe.it' \ -d amount=999 \ -d currency=eur \ -d description="One-Time Charge" \ -d metadata[ip_address]="90.90.71.253" \ -d metadata[tax_number]='IT01709820995'
Stripe::Charge.create( :source => params[:stripeToken], :receipt_email => 'billing@johndoe.it', :amount => 999, :description => 'One-Time Charge', :currency => 'eur', :metadata => { :ip_address => request.remote_ip, # An evidence of the customer's localization :tax_number => 'IT01709820995' # Proof that your customer is a business in European Union } )
\Stripe\Charge::create(array( 'source' => $_POST['stripeToken'], 'receipt_email' => 'billing@johndoe.it', 'amount' => 999, 'description' => 'One-Time Charge', 'currency' => 'eur', 'metadata' => array( 'ip_address' => $_SERVER['REMOTE_ADDR'], // An evidence of the customer's localization 'tax_number' => 'IT01709820995' // Proof that your customer is a business in European Union ) ));
import socket stripe.Charge.create( source=request.form['stripeToken'], # Using Flask receipt_email="billing@johndoe.it", amount=999, description="One-Time Charge", currency="eur", metadata={ "ip_address": socket.gethostbyname(socket.gethostname()), # An evidence of the customer's localization "tax_number": 'IT01709820995', # Proof that your customer is a business in European Union }, )
var stripe = require("stripe")( "sk_test_oCRWOhpjMI3qPvPoYYgbiWHI" ); stripe.charges.create({ source: request.body.stripeToken, // Using Express receipt_email: "billing@johndoe.it", amount: 999, description: "One-Time Charge", currency: "eur", metadata: { ip_address: request.connection.remoteAddress, // An evidence of the customer's localization tax_number: 'IT01709820995' // Proof that your customer is a business in European Union } }, function(err, charge) { // asynchronously called } );
Others metadata for Charge and Subscription
Metadata | Description |
---|---|
quantity | Put the quantity on the invoice and calculate the unit price automatically. |
tax_rate | Force the tax rate. Default is calculated by Octobat. |
product_type | Can be 'eservice', 'standard' or 'ebook'. Default is into yourtax settings. |
business_type | Default: 'B2B' if vat number is filled else 'B2C' It will force your customer to be a business ('B2B') or a consumer ('B2C'). |
sequence | Octobat's Numbering Sequence ID. There is one by default in yourdocuments settings |
notes | Some notes added to the end of the invoice |