Introduction
Getting started
Code samples are shown here. Select your target API using the tabs at the top.
The API endpoint for access with
curl
ishttps://api.processout.com
.
Welcome to the server API reference for ProcessOut!
The server API supports 5 languages (
Node.js,
Python,
Ruby,
PHP, and
Go
) and a REST API interface that you can access using a tool
such as curl
. See the page about
setting up the APIs in the guide to learn how to
obtain and install the appropriate library for your language.
The reference shows code samples for all 5 languages and also sample
command lines using curl
in the right-hand side of the page. Use the tab
at the top-right of the window to select your target language.
To use the APIs, you will also need 2 project keys. These are text strings that uniquely identify your project to our endpoints. See the section about public and private keys in the guide to learn how to access and use these keys. Also, see the page about testing in the sandbox to learn how to modify the keys to access our safe testing environment.
Email us at help@processout.com if you have any questions about using the APIs.
Status updates
Handling errors
# Error handling with curl should be handled by checking the status
# codes of the responses. Non 2xx response codes usually mean an error
# occured during the request
// Promises should be used to check for any error
// and/or success of the request.
// Let's assume invoice has already been instantiated
invoice.save().then(
function(invoice) {
// Here, the request was successful, and invoice
// has been filled with the response's data. You
// may continue your work here, safe.
}, function(err) {
// An error occured during the request. You may
// check the error message in err.
console.log(err);
});
from processout.errors.authenticationerror import AuthenticationError
from processout.errors.notfounderror import NotFoundError
from processout.errors.validationerror import ValidationError
from processout.errors.genericerror import GenericError
from processout.errors.internalerror import InternalError
# Different type of exceptions may be thrown by the
# ProcessOut's Python library, depending on the situation.
try:
# Some ProcessOut related code
pass
except AuthenticationError as e:
print("Your API credentials couldn't be verified. " + str(e))
except NotFoundError as e:
print("The requested resource could not be found. " + str(e))
except ValidationError as e:
print("This error describes a validation error. " + str(e))
except GenericError as e:
print("This is an error that didn't match any of the above. " + str(e))
except InternalError as e:
print("Something went wrong on the ProcessOut side. This is extremely rare. " + str(e))
require "processout"
# Different type of exceptions may be thrown by the
# ProcessOut's Python library, depending on the situation.
begin
# Some ProcessOut related code
rescue ProcessOut::AuthenticationError => e:
puts "Your API credentials couldn't be verified. " + str(e)
rescue ProcessOut::NotFoundError => e:
print("The requested resource could not be found. " + str(e))
rescue ProcessOut::ValidationError => e:
print("This error describes a validation error. " + str(e))
rescue ProcessOut::GenericError => e:
print("This is an error that didn't match any of the above. " + str(e))
rescue ProcessOut::InternalError => e:
print("Something went wrong on the ProcessOut side. This is extremely rare. " + str(e))
end
<?php
// Different type of exceptions may be thrown by the
// ProcessOut's PHP library, depending on the situation.
try
{
// Some ProcessOut related code
}
catch(ProcessOut\Exceptions\AuthenticationException $e)
{
// Your API credentials couldn't be verified
echo $e->getMessage();
}
catch(ProcessOut\Exceptions\NotFoundException $e)
{
// The requested resource could not be found
echo $e->getMessage();
}
catch(ProcessOut\Exceptions\ValidationException $e)
{
// This error describes a validation error
echo $e->getMessage();
}
catch(ProcessOut\Exceptions\GenericException $e)
{
// This is an error that didn't match any of the above
echo $e->getMessage();
}
catch(ProcessOut\Exceptions\InternalException $e)
{
// Something went wrong on the ProcessOut side. This
// is extremely rare
echo $e->getMessage();
}
// Different type of errors are returned by the ProcessOut's
// Go library, depending on the situation
switch e := err.(type) {
case *processout.AuthenticationError:
// Your API credentials couldn't be verified
case *processout.NotFoundError:
// The requested resource could not be found
case *processout.ValidationError:
// This error describes a validation error
case *processout.GenericError:
// This is an error that didn't match any of the above
case *processout.InternalError:
// Something went wrong on the ProcessOut side. This
// is extremely rare
default:
// The error comes from somewhere else, perhaps
// json unmarshaller
}
The server API reports errors using the standard mechanism
for your language.
For Python, Ruby and PHP, the API calls can throw exceptions
that you should catch in your code. Node.js uses error callbacks
that have a parameter derived from the
Error
class, while Go handles errors using return values.
Our naming convention for the error objects is consistent across all of the languages. The names of the objects and their meanings are shown below.
AuthenticationError |
Your API credentials could not be verified |
NotFoundError |
The requested resource could not be found |
ValidationError |
The request contained a field that couldn’t be validated |
GenericError |
An error that didn’t match any of the above |
InternalError |
Something went wrong on the ProcessOut side. This is extremely rare |
Webhooks
You can use webhooks to respond to events that happen during transactions. Webhooks, which are also known as callbacks or Instant Payment Notifications (IPN), are HTTP POST requests that ProcessOut makes to your web server whenever an event occurs. Each POST contains an ID value that is unique to the event. Your code can pass this ID to our API to retrieve the full details of the event and then respond to it. You might use the details to begin delivery of an item after a successful payment, for example.
ProcessOut can use many different payment gateways and each one will probably have its own native format for event notifications. Our API is designed to abstract over these different formats to provide simple and consistent event data, regardless of where it originates from. For ease of use, the data includes information about the transaction state associated with the event.
Prerequisites
You must enable your webhook endpoint URL in the dashboard to receive notifications. See our guide to configuring webhooks for more information.
Note that the data in the body of the POST request is always in JSON format, so you should make sure your server accepts this. Also, you should remove all CSRF protection from your webhook endpoints to receive notifications. Most frameworks and CMS enable such protection by default for security reasons, but it can block ProcessOut from making POST requests to your endpoints.
You might find it useful to queue events and process several of them at once rather than responding fully to each event as soon as it arrives. Doing this allows you to acknowledge events quickly during busy periods and then process them later when things are quieter. ProcessOut will retry webhook POST requests several times but it might be forced to give up if your server takes too long to acknowledge them. If this happens then you might miss important notifications.
Custom URL per Invoice
curl -X POST https://api.processout.com/invoices \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d customer_id="cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF" \
-d name="Amazing item" \
-d amount="4.99" \
-d currency="USD" \
-d webhook_url="https://superstore.com/webhooks"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().create({
customer_id: "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
name: "Amazing item",
amount: "4.99",
currency: "USD",
webhook_url: "https://superstore.com/webhooks"
}).then(function(invoice) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.new_invoice().create({
"customer_id": "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
"name": "Amazing item",
"amount": "4.99",
"currency": "USD",
"webhook_url": "https://superstore.com/webhooks"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.invoice.create(
"customer_id": "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
name: "Amazing item",
amount: "4.99",
currency: "USD",
webhook_url: "https://superstore.com/webhooks"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$invoice = $client->newInvoice()->create(array(
"customer_id" => "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
"name" => "Amazing item",
"amount" => "4.99",
"currency" => "USD",
"webhook_url" => "https://superstore.com/webhooks"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
iv, err := client.NewInvoice().Create(processout.InvoiceCreateParameters{
Invoice: &processout.Invoice{
CustomerID: processout.String("cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"),
Name: processout.String("Amazing item"),
Amount: processout.String("4.99"),
Currency: processout.String("USD"),
WebhookURL: processout.String("https://superstore.com/webhooks"),
},
})
You might sometimes find it useful to define custom webhook endpoints for each
order. You can do this by providing a value for webhook_url
when you
create a new Invoice object, as shown in the example. Any event that
is specific to the Invoice will be sent to both to webhook_url
and the usual
webhook URL defined in the dashboard.
Usage
# Webhooks are not supported with cURL.
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// req is filled with the decoded json data from the request body
client.newEvent().find(req["event_id"]).then(function(event) {
// We may now access the event
var data = event.getData();
switch (data["name"]) {
case "invoice.completed":
// Successful payment
break;
case "invoice.pending":
// Payment still needs some time to be processed
break;
// ...
default:
console.log("Unknown webhook action");
return;
}
}, function(err) {
// An error occured, most likely the event was coming from an
// untrusted source
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# req is filled with the decoded json data from the request body
event = client.new_event().find(req["event_id"])
data = event.data
if data["name"] == "invoice.completed":
# Successful payment
pass
elif data["name"] == "invoice.pending":
# Payment still needs some time to be processed
pass
# ...
else:
# Shouldn't be here..
print("Unknown webhook action")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# req is filled with the decoded json data from the request body
event = client.event.find(req.event_id)
data = event.data
if data["name"] == "invoice.completed"
# Successful payment
elsif data["name"] == "invoice.pending"
# Payment still needs some time to be processed
# ...
else
# Shouldn't be here..
puts "Unknown webhook action"
end
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$reqRaw = trim(file_get_contents("php://input"));
$req = json_decode($reqRaw, true);
$event = $client->newEvent()->find($req["event_id"]);
$data = $event->getData();
switch($data["name"])
{
case "invoice.completed":
// Successful payment
break;
case "invoice.pending":
// Payment still needs some time to be processed
break;
// ...
default:
echo "Unknown webhook action"; exit();
}
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
// EventData is the definition of a ProcessOut Event data
type EventData struct {
Name string `json:"name"`
Sandbox bool `json:"sandbox"`
Invoice *processout.Invoice `json:"invoice"`
}
// ProcessOutWebhook is the definition of a ProcessOut webhook
type ProcessOutWebhook struct {
EventID string `json:"event_id"`
}
func handleProcessOutWebhooks(w http.ResponseWriter,
r *http.Request) {
defer r.Body.Close()
reqRaw, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
// Decode the webhook
webhook := &ProcessOutWebhook{}
json.Unmarshal(reqRaw, &webhook)
// Fetching the associated event
event, err := client.NewEvent().Find(webhook.EventID)
if err != nil {
// Webhook not found, most likely coming from an
// insecure source
w.WriteHeader(http.StatusBadRequest)
return
}
e, _ := event.(EventData)
switch e.Name {
case "invoice.completed":
// Successful payment
case "invoice.pending":
// Payment still needs some time to be processed
// ...
default:
// Return an HTTP OK response so that unsuported
// webhooks do not get sent again
w.WriteHeader(http.StatusOK)
return
}
}
Each webhook POST request from ProcessOut only contains the ID value of the associated event. Use this ID to fetch the full set of event data using our API.
Resources
Creating resources
curl -X POST https://api.processout.com/invoices \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d customer_id="cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc" \
-d name="Amazing item" \
-d statement_descriptor="amazing item" \
-d amount="4.99" \
-d currency="AUD"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().create({
customer_id: "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
name: "Amazing item",
statement_descriptor: "amazing item",
amount: "4.99",
currency: "AUD"
}).then(function(invoice) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.new_invoice().create({
"customer_id": "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"name": "Amazing item",
"statement_descriptor": "amazing item",
"amount": "4.99",
"currency": "AUD"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.invoice.create(
customer_id: "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
name: "Amazing item",
statement_descriptor: "amazing item",
amount: "4.99",
currency: "AUD"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$invoice = $client->newInvoice()->create(array(
"customer_id" => "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"name" => "Amazing item",
"statement_descriptor" => "amazing item",
"amount" => "4.99",
"currency" => "AUD"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
iv, err := client.NewInvoice().Create(processout.InvoiceCreateParameters{
Invoice: &processout.Invoice{
CustomerID: processout.String("cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc"),
Name: processout.String("Amazing item"),
StatementDescriptor: processout.String("amazing item"),
Amount: processout.String("4.99"),
Currency: processout.String("AUD"),
},
})
The server API uses resource objects to represent the
different types of data that ProcessOut manages for you (for example,
Invoice
, Customer
and
Transaction
).
Browse the Resource types section of the sidebar to learn more
about the structure of these objects.
There are several types of resource that you create explicitly
when you need them. For example, you must create an Invoice
before you can accept a payment and you can create a
Customer
to store payment details for a user.
The create()
function for these types lets you pass a parameter object
with details of the data you want to store. The code sample shows how to
create an Invoice
with values for the customer_id
, name
, amount
and other fields.
Response:
{
"invoice": {
"id": "iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"subscription_id": null,
"customer_id": "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"token_id": null,
"details": null,
"transaction_id": "tr_qQI20QnTYPXK1MALJNfkOCjK8nycUObl",
"name": "Amazing item",
"amount": "4.99",
"currency": "AUD",
"metadata": {},
"gateway_data": {},
"exemption_reason_3ds2": null,
"challenge_indicator": null,
"sca_exemption_reason": null,
"statement_descriptor": "amazing item",
"merchant_initiator_type": null,
"require_backend_capture": null,
"card_verification": null,
"return_url": null,
"cancel_url": null,
"webhook_url": null,
"sandbox": true,
"url": "https://checkout.processout.com/test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x/iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4",
"created_at": "2022-07-07T09:25:12.680256Z",
"risk": {
"score": null,
"is_legit": null,
"skip_gateway_rules": null
},
"device": {
"id": null,
"channel": null,
"ip_address": null
},
"shipping": {
"amount": "0",
"method": null,
"provider": null,
"delay": null,
"address1": null,
"address2": null,
"city": null,
"state": null,
"country_code": null,
"zip": null,
"phone_number": null,
"expects_shipping_at": null,
"relay_store_name": null
},
"external_fraud_tools": null,
"incremental": null,
"tax": {
"rate": null,
"amount": null
},
"payment_type": null
},
"success": true
}
The response returned by create()
is the new Invoice
containing
your specified data among many other fields. One of the most important
fields is id
, which contains a unique ID string for the object. You
will use the id
value extensively as a way to fetch objects and
refer to them in the fields of other objects.
Fetching resources
curl https://api.processout.com/invoices/iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4 \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4").then(
function(invoice) {
// Invoice was fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.new_invoice().find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.invoice.find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer = $client->newInvoice()->find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust, err := client.NewInvoice().Find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4")
You can pass a resource’s id
to the find()
function to fetch the data for that resource.
You may need to store the id
strings of important objects in your database
for easy access. For example, you might keep the ID of a
Customer
object along with the user’s username and
password so you can easily fetch the object after the user logs in.
Response:
{
"invoice": {
"id": "iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"subscription_id": null,
"customer_id": "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"token_id": null,
"details": null,
"transaction_id": "tr_qQI20QnTYPXK1MALJNfkOCjK8nycUObl",
"name": "Amazing item",
"amount": "4.99",
"currency": "AUD",
.
.
}
You can see here that the response from find()
is the same object
that was created previously.
Expanding resources
curl https://api.processout.com/invoices/iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4 \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
--data-urlencode expand[]=customer
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4", {
expand: ["tokens"]
}).then(
function(invoice) {
// Invoice was fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.new_invoice().find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4", {
"expand": ["customer"]
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.invoice.find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4", {
expand: ["customer"]
})
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer = $client->newInvoice()->find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4", array(
"expand" => array("customer")
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust, err := client.NewInvoice().Find("iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4",
processout.InvoiceFindParameters{
Options: &processout.Options{
Expand: []string{"customer"},
}),
})
If you look at the description of the Invoice
object, you will notice that some of its fields are marked as expandable.
For example, the customer
field of Invoice
is an expandable
Customer
object. What this means is that the
field represents another resource object stored elsewhere. By default,
only the id
value of the Customer
sub-resource is fetched
when you fetch the Invoice
object. You can use this id
to retrieve
the sub-resource using the find()
function for that object type in a separate
API call. However, you also have the option to
expand the sub-resource, which means that all of its data will be
included in the main resource as well as its id
value.
The find()
function for each resource type has an options
parameter that comes after the id
that you want to fetch. One of the
options is an expand
array that lists the names of all fields that you
want to expand when you fetch the main object.
The sub-resources may have other nested sub-resources of their own.
Supply a “path” to expand these nested fields using the familiar object dot
notation. For example, to expand the Tokens
field of a Customer
in a Transaction
,
you can set expand
to customer.tokens
when you fetch the Transaction
object.
This will first expand the transaction’s customer
field, and then the Customer
object’s tokens
field.
Response:
{
"invoice": {
"id": "iv_0kJ1i4d06uViosJjCKpUHzKeauffMom4",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"subscription_id": null,
"customer": {
"id": "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"tokens": null,
"subscriptions": null,
"transactions": null,
"balance": "0",
"currency": "AUD",
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"address1": "999 Letsby Avenue",
.
.
},
"customer_id": "cust_CgdhFgj5QEv5I8dx6tHxVVrgxBDDzAgc",
"token_id": null,
"details": null,
.
.
}
If you compare the response to the one generated
without expanding the customer
field, you can see that both the full details of
the customer and the customer_id
are now included as separate fields, while the
rest of the Invoice
is the same as before.
Listing resources
curl -X GET -G https://api.processout.com/customers \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
--data-urlencode limit=20 \
--data-urlencode order=asc
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCustomer().all({
limit: 20,
order: "asc"
}).then(function(customers) {
// Customers were fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customers = client.new_customer().all({
"limit": 20,
"order": "asc"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customers = client.customer.all(
limit: 20,
order: "asc"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customers = $client->newCustomer()->all(array(
"limit" => 20,
"order" => "asc"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
customers, err := client.NewCustomer().All(processout.CustomerAllParameters{
Options: &processout.Options{
Limit: 20,
Order: "asc",
},
})
Each resource type has an all()
function that fetches all objects
of that type that exist in your project. The full list of objects might
contain a large number of items and so it is useful to fetch just a
short section of the list at a time. The section that you fetch is known
as a page and the technique of fetching a list one page at a time is known
as pagination.
To fetch the first page of the list, call the all()
function
with a limit
option to specify the maximum number of items you
want the page to contain. The page size defaults to 10 items if you omit
the limit
option or set it to zero. You can also pass an order
option with
a value of asc
or desc
to sort the page into ascending or
descending order of sequence (the order defaults to desc
if you omit
this option).
curl -X GET -G https://api.processout.com/customers \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
--data-urlencode start_after=cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD \
--data-urlencode limit=20 \
--data-urlencode order=asc
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCustomer().all({
startAfter: "cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD",
limit: 20,
order: "asc"
}).then(function(customers) {
// Customers were fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customers = client.new_customer().all({
"start_after": "cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD",
"limit": 20,
"order": "asc"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customers = client.customer.all(
start_after: "cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD",
limit: 20,
order: "asc"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customers = $client->newCustomer()->all(array(
"startAfter" => "cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD",
"limit" => 20,
"order" => "asc"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
customers, err := client.NewCustomer().All(processout.CustomerAllParameters{
Options: &processout.Options{
StartAfter: "cust_FM5ZDn3PjkCmDVXYnqrZFrnlypilDicD",
Limit: 20,
Order: "asc",
},
})
To fetch pages after the first, you use cursor-based pagination.
This fetches a page of items relative to an item that you specify,
which is called the cursor. The page contains the items that come
either before or after the cursor (at your choice) but it does not
include the cursor itself. For example, to fetch the second page,
pass the id
of the last item in the first page to all()
using
the start_after
option. If you want the fetch the items that come
before the cursor, then pass its id
as the end_before
option.
Note that you cannot supply both start_after
and end_before
in the same call.
Response:
{
"count": 10,
"customers": [
{
"id": "cust_1g4YXoiOPBkCnsedpOmUS6wfmJaxtAAZ",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"tokens": null,
.
.
},
{
"id": "cust_jXpiWXv7yYbKeYZzyQifEDSHYzuElQxr",
"project_id": "proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"tokens": null,
.
.
},
.
.
],
"has_more": true,
"limit": 10,
"order": "asc",
"success": true,
"total_count": 642
}
Note that the object returned by all()
contains the page of items
in an array named after the item type (for example, customers
for a
list of Customer
objects). It also has a few other useful data
fields:
-
count
: The number of items in the page (which is not necessarily the same as thelimit
value that you specify). -
has_more
: This isfalse
when you usestart_after
and the page contains the last item in the list or when you useend_before
and the page contains the first item. If you are working through the pages in sequence then this value essentially means that you have not reached the end of the list yet. -
total_count
: This gives the total number of items in the full list. You can callall()
with alimit
value of 1 and ignore the page array if you only want to find thetotal_count
for the list.
Adding metadata
The main objects in the server API have a metadata
object field that you can
use to store any data you like as key-value pairs. For example, you could
store your own internal ID values here to help with order tracking.
There are 2 reserved keys in the metadata
object that you should not use for
your own data:
- taxes_amount is zero or a positive number representing the taxes included in the
amount
- shipping_amount is a zero or a positive number representing the shipping costs included in the
amount
Note that the metadata
object has the following restrictions (which
cannot be reconfigured):
- A maximum of 50 key-value pairs per object
- Keys must be no more than 40 characters in length
- Values must be no more than 500 characters in length
Resource types
Invoices
Invoice
objects are very important in the payment process. You must
create an invoice before you can accept a payment, but you can
also use it to store many other pieces of information about a purchase.
For example:
- Shipping information
- Details and availability of the items to be purchased
- Sales tax
See the guide page about creating an invoice for a full description of how it fits into the payment flow.
Note that for any fields that refer to an amount of money (such as amount
and
discount_amount
), you should specify the amount in the major unit of the
currency rather than the minor unit (so this would mean dollars rather
than cents if the currency is USD, for example).
Invoice attributes
id string Read-only |
String value that uniquely identifies this invoice. |
project project_id Project expandable |
Project that the invoice belongs to. |
url string Read-only |
URL of the ProcessOut checkout page |
customer customer_id Customer expandable |
Customer linked to the invoice (generally the one making the purchase). |
transaction transaction_id Transaction expandable |
Transaction generated when the invoice is authorized or captured. |
token token_id Token expandable |
Token that was used, or will be used, to capture the payment. If the invoice is linked to a customer (via the customer field) then this token must belong to them. |
details list of InvoiceDetail |
Details of the items or products that are being purchased. |
risk InvoiceRisk object |
Risk assessment for the invoice. |
device InvoiceDevice object |
Information about the device (web, mobile, other) that was used to start the purchase. |
external_fraud_tools InvoiceExternalFraudTools object |
Information to forward to external fraud tools. |
shipping InvoiceShipping object |
Shipping information for the invoice. |
name string Required |
Name of the invoice (often an internal ID code from the merchant’s systems). Maximum 80 characters long |
statement_descriptor string |
Item that will be listed for this purchase on the customer’s bank statement. Maximum 22 characters long, should only contain letters, numbers, spaces, dots and forward slashes |
statement_descriptor_phone string |
Support phone number for this purchase on the customer’s bank statement. |
statement_descriptor_city string |
City shown for this purchase on the customer’s bank statement. |
statement_descriptor_company string |
Your company name to show on the customer’s bank statement. |
statement_descriptor_url string |
Support URL for this purchase on the customer’s bank statement. |
gateway_data Dictionary |
Information to pass to a particular gateway, in the form of key-value pairs (string - string). |
amount string Required |
Amount to be paid. |
currency string Required |
Currency for payment of the invoice, in ISO 4217 format (for example, USD ).Must be a valid ISO 4217 currency code with 3 characters |
merchant_initiator_type string |
For Merchant Initiated Transactions (MITs), set this field to one-off to denote a single payment or recurring to denote a repeatable payment (such as a sequence of subscription renewals). |
return_url string |
For APMs, this is the URL to return to the app after payment is accepted. Must be a valid URL |
cancel_url string |
For APMs, this is the URL to return to the app after payment is canceled. Must be a valid URL |
webhook_url string |
Custom webhook URL for this purchase. Must be a valid URL |
require_backend_capture boolean Read-only |
Denotes whether or not this invoice must be captured server-side. |
incremental boolean Read-only |
Denotes whether or not you can apply incremental authorizations to this invoice. |
metadata Metadata dictionary |
Metadata related to the invoice, in the form of key-value pairs (string - string). |
sca_exemption_reason string |
Optional reason for requesting SCA exemption (Note: This must also be supported by the PSP. Please contact us for more information.) Allowed values are: “low-value”, “trusted-beneficiary” or “transaction-risk-analysis” |
challenge_indicator string |
Optional challenge indicator field when requesting 3DS2 (Note: This must also be supported by the PSP. Please contact us for more information.) Allowed values are: “no-preference”, “no-challenge-requested”, “challenge-requested”, “challenge-requested-mandate”, “no-challenge-requested-tra-performed”, “no-challenge-requested-data-share-only”, “no-challenge-requested-sca-performed”, “no-challenge-requested-whitelist-exemption”, “challenge-requested-whitelist-prompt” or “cb-scoring” |
tax InvoiceTax object |
Tax information for the invoice. |
payment_type string |
Optional information about the payment type Allowed values are “moto” or “ecommerce” |
sandbox boolean Read-only |
Denotes whether or not this invoice was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when the invoice was created. |
InvoiceDetail attributes
id string Read-only |
String value that uniquely identifies this invoice detail. |
name string Required |
Name of the item or product, which represents an item on a receipt. Maximum 80 characters long |
type string |
Item or product type. Set this to anything suitable. Maximum 30 characters long |
amount string Required |
Amount charged for this item or product. |
quantity integer |
Quantity of the item or product. Default value is 1. |
metadata Metadata dictionary |
Metadata related to the invoice detail, in the form of key-value pairs (string - string). |
category string |
Category of the item or product. Can be food , entertainment , home , appliance , bidding , gift , technology , media , communication , health , sport , personal-service , professional-service , clothing , travel , transport or other . |
reference string |
Reference of the item or product. Maximum 255 characters long |
description string |
Description of the item or product. Maximum 255 characters long |
brand string |
Brand of the item or product. Maximum 80 characters long |
model string |
Model of the item or product. Maximum 80 characters long |
discount_amount string |
Discount amount (when the discount is listed as a separate item on a receipt). |
condition string |
Condition of the product. Can be new , refurbished , used or other . |
marketplace_merchant string |
Marketplace merchant ID of the item or product. |
marketplace_merchant_is_business boolean |
Denotes whether or not the marketplace merchant is a business. |
marketplace_merchant_created_at RFC1123 date or timestamp |
Date and time when the merchant was created. |
InvoiceRisk attributes
score string |
Scoring of the invoice. No validation done on this field because it is used to forward risk information to compatible payment providers. Maximum 12 characters long |
is_legit bool |
Denotes whether or not the invoice is legitimate. |
skip_gateway_rules bool |
Flag to skip payment gateway fraud engine rules. (This is only available on certain compatible gateways. Contact us for more information.) |
InvoiceDevice attributes
id string |
ID of the device. This can be anything but would usually be a UUID generated by a third-party anti-fraud solution. Maximum 100 characters long |
channel string |
Channel used by the device. Can be web , ios , android or other . |
ip_address string |
IP address of the device. Must be a valid IP address |
InvoiceShipping attributes
amount string |
Amount charged for shipping. |
method string |
Delivery method. Can be web , collect-at-shop , relay , travel-station , home , shipping , locker or other . |
provider string |
Delivery provider. Maximum 32 characters long |
delay string |
Shipment delay. Can be express , priority , standard or other . |
address1 string |
First line of the delivery address. Maximum 255 characters long |
address2 string |
Second line of the delivery address. Maximum 255 characters long |
state string |
State or county of the delivery address. Maximum 80 characters long |
city string |
City of the delivery address. Maximum 80 characters long |
country_code string |
Country code (US , FR …) of the delivery address.Must be a valid ISO 3166 country code with 2 characters |
zip string |
ZIP code of the delivery address. Maximum 16 characters long |
phone_number string |
Phone number of the shipment recipient. Maximum 17 characters long (Note: “+” will be treated as “00”) |
expects_shipping_at RFC1123 date or timestamp |
Expected date of delivery. |
relay_store_name string |
Name of the store that the order must be collected from. Maximum 100 characters long |
InvoiceTax attributes
amount string |
Amount is zero or a positive number representing the tax included in the amount. |
rate string |
Rate is a percentage (0 to 100) representing the rate of tax included in the amount. |
InvoiceExternalFraudTools attributes
forter string |
Information for the Forter fraud prevention service. |
Creating an invoice
curl -X POST https://api.processout.com/invoices \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d customer_id="cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF" \
-d name="Amazing item" \
-d statement_descriptor="amazing item" \
-d amount="4.99" \
-d currency="USD"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().create({
customer_id: "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
name: "Amazing item",
statement_descriptor: "amazing item",
amount: "4.99",
currency: "USD"
}).then(function(invoice) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.new_invoice().create({
"customer_id": "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
"name": "Amazing item",
"statement_descriptor": "amazing item",
"amount": "4.99",
"currency": "USD"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.invoice.create(
"customer_id": "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
name: "Amazing item",
statement_descriptor: "amazing item",
amount: "4.99",
currency: "USD"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$invoice = $client->newInvoice()->create(array(
"customer_id" => "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF",
"name" => "Amazing item",
"statement_descriptor" => "amazing item",
"amount" => "4.99",
"currency" => "USD"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
iv, err := client.NewInvoice().Create(processout.InvoiceCreateParameters{
Invoice: &processout.Invoice{
CustomerID: processout.String("cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"),
Name: processout.String("Amazing item"),
StatementDescriptor: processout.String("amazing item"),
Amount: processout.String("4.99"),
Currency: processout.String("USD"),
},
})
You can supply many pieces of information when you create an Invoice
object.
See the section about creating resources to learn
how to pass data fields to the create()
function.
At a minimum, you must supply a name
, amount
and currency
to create
the Invoice
, as shown in the code sample.
Fetching an invoice
curl -X GET https://api.processout.com/invoices/iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newInvoice().find("iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl").then(
function(invoice) {
// The invoice was fetched
}, function(err) {
// The invoice could not be found
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.new_invoice().find("iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
invoice = client.invoice.find("iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$invoice = $client->newInvoice()->find("iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
iv, err := client.NewInvoice().Find("iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl")
You can fetch an Invoice
object using its id
value. See the section about
fetching resources for more information.
Capturing an invoice
curl -X POST https://api.processout.com/invoices/iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl/capture \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d source=card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
invoice.capture("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ").then(
function(transaction) {
// The invoice was captured and returned a transaction
}, function(err) {
// The invoice could not be captured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
transaction = invoice.capture("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
transaction = invoice.capture("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
$transaction = $invoice->capture("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
tr, _ := iv.Capture("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
Use the capture()
function to capture payment on an invoice. This returns
a Transaction
object if it is successful or
reports an error if the request cannot be handled. See the guide page about
capturing a payment for examples and for more detail
about how capturing fits into the payment flow.
Note that when capture()
returns the Transaction
object, this does not
necessarily mean that the payment has succeeded immediately. You should check the
status
field of the object for completed
status to confirm the payment. We recommend that you use
webhooks to receive updates about the status of the transaction
because it can change even after the capture()
call has returned.
You must provide a payment source for the capture (card,
token, or gateway request) unless it has been
authorized previously. You can also pass an options
object as a second parameter to enable extra features on Payment Service
Providers (PSPs) that support them. The options include:
-
capture_amount
: Some PSPs support partial captures, where the amount you eventually capture is less than the amount you originally specified in the invoice. Usecapture_amount
to choose the amount for a partial capture, if your PSPs provide this feature. For PSPs that do not support partial captures, you can get the same effect by capturing the full amount and then issuing a partial refund later. -
capture_statement_descriptor
: When you create an invoice, you can supply a statement descriptor, which is the text that will appear on the customer’s bank statement for the payment. Some PSPs let you change the statement descriptor during capture. Setcapture_statement_descriptor
to the new text you want to use for the descriptor or omit this option to use the original descriptor from the invoice. -
invoice_detail_ids
: When you create an invoice, you can supply a set of invoice details to represent separate items being purchased (which might be items in a shopping cart, say). Some PSPs let you restrict the purchase to just a subset of these items during capture. Setinvoice_detail_ids
with an array that contains theid
values of theInvoiceDetail
objects that you want to include. If you omit this option (or the PSP does not support it) then the full list from thedetails
field of the invoice will be used.
Note that if you do authorize the payment before capture then you can simply
call the capture()
function without any parameters.
Authorizing an invoice
curl -X POST https://api.processout.com/invoices/iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl/authorize \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d source=card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ \
-d auto_capture_at="2022-10-02T15:00:00Z" # optional if you want us to auto capture for you
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
invoice.authorize("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ", {
// optional if you want us to auto capture for you
"auto_capture_at": "2022-10-02T15:00:00Z"
}).then(
function(transaction) {
// The invoice was authorized and returned a transaction
}, function(err) {
// The invoice could not be authorized
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
transaction = invoice.authorize("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ", {
# optional if you want us to auto capture for you
"auto_capture_at": "2022-10-02T15:00:00Z"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
transaction = invoice.authorize("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ", (
# optional if you want us to auto capture for you
auto_capture_at: "2022-10-02T15:00:00Z"
))
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
$transaction = $invoice->authorize("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ", array(
// optional if you want us to auto capture for you
"auto_capture_at" => "2022-10-02T15:00:00Z"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
tr, _ := iv.Authorize("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ", InvoiceAuthorizeParameters{
AutoCaptureAt: "2022-10-02T15:00:00Z",
})
There are actually 2 steps involved in capturing a payment. First, the payment is authorized. This step involves checking that the customer has enough money in their account to settle the payment and then “locking” that money so that it is not available for other payments. The second step is the capture itself, which involves booking the final money transfer between banks.
For
Merchant Initiated Transactions
(MITs), the payment is automatically authorized when you call capture()
but you
can call authorize()
explicitly to perform the authorization as a separate step.
You can authorize a payment up to 7 days before capturing it, which may be useful
for fraud checking, for example.
For Customer Initiated Transactions (CITs) you must authorize the invoice separately on the client to comply with Strong Customer Authentication (SCA) legislation. See the page about authorizing a payment for more information and examples.
You can also use the auto_capture
option with the authorize()
function to
arrange for the payment to be captured automatically after a time delay. The
value for auto_capture
is a date and time in RFC 3339 format that specifies
the time when you want the capture to happen.
Note that if you do authorize a payment then you can call the capture()
function
without specifying a payment source. The source you supply during authorization
will be used for the capture.
Incrementing an invoice’s authorization
curl -X POST https://api.processout.com/invoices/iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl/increment_authorization \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
-d amount="10.00"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
invoice.incrementAuthorization("10.00").then(
function(transaction) {
// The authorization amount was incremented and returned a transaction
}, function(err) {
// The authorization amount could not be incremented
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = invoice.increment_authorization("10.00")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = invoice.increment_authorization("10.00")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$transaction = $invoice->incrementAuthorization("10.00");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tr, _ := iv.IncrementAuthorization("10.00")
Some PSPs support incremental authorizations. This means that if the payment
has been authorized then you can increase the amount to be paid before it is
finally captured. Use the IncrementAuthorization()
function on the invoice
with the amount you want to increment by as a parameter.
You can increment an invoice if its incremental
field is true
and if its
transaction status is authorized
. You can
increment more than once but note that you cannot increment an invoice after
it has been captured.
Voiding an invoice
curl -X POST https://api.processout.com/invoices/iv_MgeLS2Rr3ZGwjqOvDvYSuWx7ce88luXl/void \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// The source could also be a token tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy
invoice.void().then(
function(transaction) {
// The invoice was voided and returned a transaction
}, function(err) {
// The invoice could not be voided
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = invoice.void()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = invoice.void()
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$transaction = $invoice->void();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tr, _ := iv.Void()
If you have authorized an invoice (but
not captured it yet) then you can call the
void()
function to cancel the authorization. The function requires
no parameters and will only succeed on an invoice whose
transaction status is authorized
.
The void()
call returns an updated Transaction
object with its
status
field set to voided
.
Customers
The Customer
object contains information about a customer, including
contact details. You can also use it to create a customer token from
a card or APM token. The customer token stores the payment details for repeated
use in the future. (By contrast, you can only use a card or APM token to make a
single payment.) When you have created at least one valid token for the customer,
you can use the id
value of the Customer
object itself as a payment source
that will reference the token. See the guide page about
creating a customer token
for full details about how to create and use the token.
Customer attributes
id string Read-only |
String value that uniquely identifies the customer. |
project project_id Project expandable |
Project that the customer belongs to. |
default_token default_token_id Token expandable |
Default token for the customer. This is used as the payment token when you supply the customer’s ID as a payment source. |
tokens list of Token expandable |
Tokens that belong to the customer (which can be cards or other payment methods). |
transactions list of Transaction expandable |
Transactions that were started by the customer (which can be in any transaction state). |
balance string |
Customer’s balance (which can be positive or negative). |
currency string |
Currency unit for the customer’s balance in ISO 4217 format (for example, USD ). Note that you cannot change the currency unit after you set it the first time.Must be a valid ISO 4217 currency code with 3 characters |
email string |
Customer’s email address. Must be a valid email |
first_name string |
First name of the customer. Maximum 80 characters long |
last_name string |
Last name of the customer. Maximum 80 characters long |
address1 string |
First line of the customer’s address. Maximum 80 characters long |
address2 string |
Second line of the customer’s address. Maximum 80 characters long |
city string |
City of the customer’s address. Maximum 80 characters long |
state string |
State or county of the customer’s address. Maximum 80 characters long |
zip string |
ZIP code of the customer’s address. Maximum 16 characters long |
country_code string |
Country code of the customer’s address (US , FR …).Must be a valid ISO 3166 country code with 2 characters |
phone_number string |
Phone number of the customer. Maximum 17 characters long (Note: “+” will be treated as “00”) |
legal_document string |
Legal document number (required in some countries). Maximum 255 characters long; example for a CPF document in Brazil: 853.513.468-93 |
ip_address string |
IP address of the customer. Must be a valid IPv4 or IPv6 address |
sex string |
Sex of the customer. Can be male or female . |
date_of_birth RFC1123 date or timestamp |
Customer’s date of birth. |
is_business boolean |
Denotes whether or not the customer represents a business. |
metadata Metadata dictionary |
Metadata related to the customer, in the form of key-value pairs (string - string). |
registered_at RFC1123 date or timestamp |
Date when the customer was registered on your platform. This defaults to the same date as created_at if you omit it. |
sandbox boolean Read-only |
Denotes whether or not this customer was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this customer was created. |
Creating a customer
curl -X POST https://api.processout.com/customers \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d email="john@smith.com" \
-d first_name="John" \
-d last_name="Smith"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
var customer = client.newCustomer().create({
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith"
}).then(function(customer) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.new_customer().create({
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.customer.create(
email: "john@smith.com",
first_name: "John",
last_name: "Smith"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer = $client->newCustomer()->create(array(
"email" => "john@smith.com",
"first_name" => "John",
"last_name" => "Smith"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust, err := client.NewCustomer().Create(processout.CustomerCreateParameters{
Customer: &processout.Customer{
Email: processout.String("john@smith.com"),
FirstName: processout.String("John"),
LastName: processout.String("Smith"),
},
})
You can supply many pieces of information when you create an Customer
object.
See the section about creating resources to learn
how to pass data fields to the create()
function.
Fetching a customer
curl -X GET https://api.processout.com/customers/cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCustomer().find("cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb").then(
function(customer) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.new_customer().find("cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.customer.find("cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer = $client->newCustomer()->find("cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust, err := client.NewCustomer().Find("cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb")
You can fetch a Customer
object using its id
value. See the section about
fetching resources for more information.
Updating a customer
curl -X PUT https://api.processout.com/customers/cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d first_name="New Name"
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
customer.setFirstName("New name");
customer.save();
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer.first_name = "New name"
customer.save()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer.first_name = "New name"
customer.save
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer->setFirstName("New name");
$customer->save();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust.FirstName = processout.String("New name")
cust.Save()
You can update a Customer
object that you have already created
by modifying its data fields directly and then calling the save()
function on the
object. You would most likely update an customer’s details after first
fetching them from storage.
Deleting a customer
curl -X DELETE https://api.processout.com/customers/cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCustomer({
id: "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"
}).delete().then(
function(ok) {
//
}, function() {});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.new_customer({
"id": "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"
}).delete()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
customer = client.customer(
id: "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"
).delete
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$customer = $client->newCustomer(array(
"id" => "cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"
))->delete();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
cust, _ := client.NewCustomer(&processout.Customer{
ID: processout.String("cust_LvjCcLOVe6iWn2aeCNhNmK7RbbG6K8XF"),
}).Delete()
You can delete a customer if it is no longer useful but note that you cannot undo this action and the data will be lost permanently.
Listing tokens
curl -X GET https://api.processout.com/customers/cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks/tokens \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
customer.fetchTokens().then(
function(tokens) {
// And let's say our customer wants to remove its first token
tokens[0].delete();
}, function(err) {
// The customer's tokens could not be fetched
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
tokens = customer.fetch_tokens()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
tokens = customer.fetch_tokens()
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$tokens = $customer->fetchTokens();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tok, _ := cust.FetchTokens()
You can create more than one token for a customer to let them choose from
several payment options. The Customer
object also has a default_token
field. Assign a token to this field to use it for payment when you supply
the customer ID as a source.
Listing transactions
curl -X GET https://api.processout.com/customers/cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb/transactions \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCustomer({
id: "cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb"
}).fetchTransactions().then(
function(transactions) {
// Transactions were fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = client.new_customer({
"id": "cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb"
}).fetch_transactions()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = client.customer(
id: "cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb"
).fetch_transactions()
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$transaction = $client->newCustomer(array(
"id" => "cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb"
))->fetchTransactions();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tr, err := client.NewCustomer(&processout.Customer{
ID: "cust_UVYZP5I5741rFHQDEZXGLm777fCZzQAb",
}).FetchTransactions()
Use fetchTransactions()
to get a list of all transactions for
a customer. This function lets you paginate the list,
so you can work with a large number of transactions easily.
Cards
A Card
object represents a credit or debit card. It contains many
useful pieces of information about the card but importantly, it does
not contain the full card number and CVC (which are kept securely in
the ProcessOut Vault). However, you can use the card for a single payment by
creating a card token with it. If you want to use the card for multiple
payments then you can use the card token to create a reusable
customer token. Note that once you have used the card token
either for a payment or to create a customer token, the card token becomes
invalid and you cannot use it for any further actions.
You must normally create a card token using the client API to comply with Strong Customer Authentication legislation. See the guide page about tokenizing a card to learn how to create the token securely on the client.
You can use the expires_soon
field of the Card
object to identify cards
that will become invalid in the near future. When we detect that a card is
about to expire, we will also fire an event to notify your
webhook endpoint. You might respond to this by prompting the
customer to supply a new payment card, for example.
Card attributes
id string Read-only |
String value that uniquely identifies the card. |
project project_id Project expandable |
Project that the card belongs to. |
token Token expandable |
Customer token created using this card object (which will be empty if no token has been created yet). |
scheme string Read-only |
Scheme of the card, such as Visa or Mastercard. |
co_scheme string Read-only |
Co-scheme of the card, such as Carte Bancaire. |
preferred_scheme string Read-only |
Preferred scheme defined by the Customer. This gets priority when processing the Transaction. |
type string Read-only |
Card type (debit or credit ). |
bank_name string Read-only |
Name of the card’s issuing bank. |
brand string Read-only |
Brand of the card, such as Electron, Classic or Gold. |
category string Read-only |
Card category (consumer or commercial ). |
iin string Read-only |
Issuer identification number. Corresponds to the first 6 or 8 digits of the main card number. |
last_4_digits string Read-only |
Last 4 digits of the card. |
fingerprint string Read-only |
Hash value that remains the same for this card even if it is tokenized several times. Note that this value is different for each project and cannot be used for payment. |
exp_month integer Read-only |
Month of the expiration date. |
exp_year string Read-only |
Year of the expiration date. |
cvc_check string Read-only |
CVC check status. Can be pending , unavailable , unknown , failed , or passed . |
avs_check string Read-only |
AVS check status. Can be pending , unavailable , unknown , failed , failed-name , failed-address , failed-postal , failed-address-passed-postal , failed-postal-passed-address , or passed . |
token_type string |
Contains the name of a third party tokenization method (such as applepay ), if one was used or null otherwise. |
name string |
Cardholder’s name. Maximum 255 characters long |
address1 string |
First line of cardholder’s address. Maximum 255 characters long |
address2 string |
Second line of cardholder’s address. Maximum 255 characters long |
city string |
City of cardholder’s address. Maximum 255 characters long |
state string |
State or county of cardholder’s address. Maximum 255 characters long |
country_code string |
Country code of cardholder’s address. Must be a valid ISO 3166 country code with 2 characters |
zip string |
ZIP code of cardholder’s address. Maximum 16 characters long |
ip_address string |
IP address of the cardholder Must be a valid IP address |
user_agent string |
Value of the User-Agent header of the cardholder, if one is available. |
header_accept string |
Value of the Accept header of the cardholder, if one is available. |
app_color_depth string |
Supported color depth on the cardholder’s screen, if one is available. |
app_java_enabled boolean |
Denotes whether or not Java is enabled on the cardholder device (defaults to null if unknown). |
app_language string |
Language of the cardholder’s device, if available. example: FR/fr |
app_screen_height integer |
Height in pixels of the cardholder’s screen. |
app_screen_width integer |
Width in pixels of the cardholder’s screen. |
app_timezone_offset integer |
Timezone offset of the cardholder. Timezone offset from UTC in minutes (from -12hr to +14hr) |
expires_soon boolean |
Set to true if the card will expire soon, otherwise false . |
metadata Metadata dictionary |
Metadata related to the card, in the form of key-value pairs (string - string). |
sandbox boolean Read-only |
Denotes whether or not this card was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this card was created. |
Fetching a card
curl -X GET https://api.processout.com/cards/card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newCard().find("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ").then(
function(card) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
card = client.new_card().find("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
card = client.card.find("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$card = $client->newCard()->find("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
card, err := client.NewCard().Find("card_1jSEVrx7oaRta1KEdxoMWbiGkK2MijrZ")
You can fetch a Card
object using its id
value, which is the same as
the card token. See the section about
fetching resources for more information.
If you own a PCI environment then you can also use the find()
function
to detokenize a card by fetching the original payment details. Contact
your ProcessOut account manager for more information about this feature.
Tokenizing a card
curl -X POST https://api.processout.com/cards \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d name="John Smith" \
-d number=4242424242424242 \
-d exp_month=12 \
-d exp_year=2020 \
-d cvc2=200
// NodeJS is currently not supported for Cards (please use ProcessOut.js instead)
# Python is currently not supported for Cards
# Ruby is currently not supported for Cards
// PHP is currently not supported for Cards
// Go is currently not supported for Cards
For most users, we strongly recommend using the client-side API to tokenize cards because this does not require any complex PCI DSS certifications. However, if you already comply with PCI standards then you can use the REST API endpoint directly to tokenize a card on the server. However, we do not provide any function in the server-side language SDKs to access this endpoint.
Tokens
Customer tokens (usually just called tokens for short) are objects that associate a payment source such as a card or APM token with a customer. You can only use a card or APM token once but you can make payments as many times as necessary with a customer token. This is a useful way to store payment details for a customer as a convenience but it is also essential for Merchant Initiated Transactions (MITs). See the guide page about saving a token to capture future payments to learn more about creating and using customer tokens.
Token attributes
id string Read-only |
String value that uniquely identifies the token. |
customer customer_id Customer expandable |
Customer object from which the token was created. |
gateway_configuration gateway_configuration_id GatewayConfiguration expandable |
Gateway configuration that the token is linked to (which can be empty if unused). |
card card_id Card expandable |
Card used to create the token. |
invoice invoice_id Invoice expandable |
Invoice used to verify the token. |
type string Read-only |
Source used to create the token (which will usually be a Card ). |
description string |
Description that will be sent to the tokenization gateway service. |
verification_status boolean Read-only |
If you request verification for the token then this field tracks its status. The status can have the following values: success , pending , failed , not-requested and unknown . |
is_default boolean Read-only |
Denotes whether or not this is the customer’s default token (the token used when capturing a payment using the customer’s ID as the source). |
return_url string |
For APMs, this is the URL to return to the app after payment is accepted. Must be a valid URL |
cancel_url string |
For APMs, this is the URL to return to the app after payment is canceled. Must be a valid URL |
metadata Metadata dictionary |
Metadata related to the token, in the form of key-value pairs (string - string). |
sandbox boolean Read-only |
Denotes whether or not this token was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this token was created. |
summary string Read-only |
Masked version of the payment details (for example, a card number that shows only the last 4 digits **** **** **** 4242 ). |
is_chargeable boolean Read-only |
Denotes whether or not this token is chargeable. |
manual_invoice_cancellation boolean Read-only |
If true, this lets you refund or void the invoice manually after the token is verified. |
can_get_balance boolean Read-only |
If true then you can find the balance for this token. |
Creating a token
curl -X POST https://api.processout.com/customers/cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj/tokens \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d source=card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newToken().create({
customer_id: "cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj",
source: "card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj"
}).then(function(token) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token = client.new_token().create({
"customer_id": "cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj",
"source": "card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token = client.token.create(
customer_id: "cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj",
source: "card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$token = $client->newToken()->create(array(
"customer_id" => "cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj",
"source" => "card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
token, err := client.NewToken().Create(processout.TokenCreateParameters{
Token: &processout.Token{
CustomerID: processout.String("cust_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj"),
},
Source: "card_C4hZXQTU0aWoYeenHYC0DektYDqf8ocj",
})
To create a token, you must supply the ID of the customer it will belong to and a payment source token. The source can be a card, an APM or a gateway request. For the source to be valid, you must not have used it for any previous payment or to create any other customer tokens. Once you have used the source token, it becomes invalid but its payment details can be reused by passing the customer token as a source instead.
Any tokens you create for a customer are added to the tokens
list in the
Customer
object.
Fetching a token
curl https://api.processout.com/customers/cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks/tokens/tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newToken().find("cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks",
"tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy").then(
function(token) {
// And let's say our customer wants to remove its token
token.delete();
}, function(err) {
// The customer's token could not be fetched
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token = client.new_token().find("cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks",
"tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token = client.token.find("cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks",
"tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$token = $client->newToken()->find("cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks",
"tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tok, err := client.NewToken().Find("cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks",
"tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
You can fetch a Token
object using its id
value. See the section about
fetching resources for more information.
Deleting a token
curl -X DELETE https://api.processout.com/customers/cust_WtaVdUjAGpOlbLiYWYXBR67whr91Rlks/tokens/tok_aKrYfz903uXn9MV0p8ZH7Lfly2JGtZWh \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
token.delete().then(
function(ok) {
//
}, function(err) {
// The token could not be deleted
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token.delete()
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
token.delete
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$token->delete();
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tok.Delete()
You can delete a token if it is no longer useful but note that you cannot undo this action and the data will be lost permanently.
Transactions
A Transaction
object is created when you authorize
or capture an invoice during payment.
You cannot change the fields of the object yourself but ProcessOut will
update the status
and other fields automatically as the transaction
progresses. An event is fired whenever the status of a
transaction changes. You can receive notification of the event using
webhooks.
For any fields that refer to an amount of money (such as amount
and
authorized_amount
), you should specify the amount in the major unit of the
currency rather than the minor unit (so this would mean dollars rather
than cents if the currency is USD, for example).
Note that the metadata
field of a Transaction
object is simply
copied from the Invoice
object that was used for the payment. You
cannot set or update the metadata as you can with other objects.
Transaction attributes
id string Read-only |
String value that uniquely identifies the transaction. |
project project_id Project expandable |
Project that the transaction belongs to. |
invoice invoice_id Invoice expandable |
Invoice used to create the transaction. |
customer customer_id Customer expandable |
Customer linked to the transaction. |
refunds List of Refund expandable |
List of refunds made on the transaction. |
token token_id Token expandable |
Token used to capture the transaction. |
card card_id Card expandable |
Card used to capture the transaction. |
gateway_configuration gateway_configuration_id GatewayConfiguration expandable |
Gateway configuration that was eventually used to process the transaction. |
operations List of Operation expandable |
Sequence of operations (pending, failed or successful) made on the transactions, such as authorization , capture and refund . |
name string Read-only |
Name of the transaction. |
amount string Read-only |
Amount requested when creating the transaction. |
amount_local string Read-only |
Amount requested when creating the transaction, stated in your project’s currency unit. |
authorized_amount string Read-only |
Amount that was authorized for the transaction. |
authorized_amount_local string Read-only |
Amount that was authorized for the transaction, stated in your project’s currency unit. |
captured_amount string Read-only |
Amount that was captured for the transaction. |
captured_amount_local string Read-only |
Amount that was captured for the transaction, stated in your project’s currency unit. |
refunded_amount string Read-only |
Amount that was refunded for the transaction. |
refunded_amount_local string Read-only |
Amount that was refunded for the transaction, stated in your project’s currency unit. |
available_amount string Read-only |
Amount available for the transaction (captured - refunded). |
available_amount_local string Read-only |
Amount available for the transaction (captured - refunded), stated in your project’s currency unit. |
cvc_check boolean Read-only |
Denotes whether or not a CVC check was performed during the transaction. |
avs_check boolean Read-only |
Denotes whether or not an AVS check was performed during the transaction. |
currency string Read-only |
Currency of the transaction. |
authorized boolean Read-only |
Denotes whether or not the transaction was authorized. |
captured boolean Read-only |
Denotes whether or not the transaction was captured. |
refunded boolean Read-only |
Denotes whether or not the transaction was refunded. |
voided boolean Read-only |
Denotes whether or not the transaction was voided. |
chargedback boolean Read-only |
Denotes whether or not the transaction was charged back. |
status string Read-only |
Status of the transaction (see Transaction status codes below). |
three_d_s_status string Read-only |
Status of the 3DS authentication performed on the transaction. This will be null if no authentication was performed. |
gateway_name string Read-only |
Name of the last gateway where the transaction was attempted. The operations list has the full history of the transaction. |
error_code string Read-only |
Transaction error code (null if the transaction was successful). |
error_message string Read-only |
Transaction error message (null if the transaction was successful). |
processout_fee string Read-only |
Fee taken by ProcessOut to handle the transaction. |
estimated_fee string Read-only |
Gateway fee estimated before processing the payment. |
gateway_fee string Read-only |
Fee taken by the payment gateway to process the payment. |
gateway_fee_local string Read-only |
Fee taken by the payment gateway to process the payment, stated in your project’s currency unit. |
currency_fee string Read-only |
Currency unit of the fee taken by the payment gateway (the amount is specified in the gateway_fee field). |
received_fraud_notification boolean Read-only |
Denotes whether or not the transaction received a fraud notification event. |
received_retrieval_request boolean Read-only |
Denotes whether or not the transaction received a retrieval request event. |
acquirer_name string Read-only |
Name of the merchant acquirer (null if this is not available). |
metadata Metadata dictionary |
Metadata copied from the transaction’s invoice, in the form of key-value pairs (string - string). |
sandbox boolean Read-only |
Denotes whether or not this transaction was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this transaction was created. |
Operation attributes
id string Read-only |
String value that uniquely identifies the operation. |
transaction transaction_id Transaction expandable |
The transaction that this operation belongs to. |
gateway_configuration gateway_configuration_id GatewayConfiguration expandable |
Gateway configuration that was used to process the operation. |
token token_id Token expandable |
The token that was used in the transaction (if any). |
card card_id Card expandable |
The card that was used in the transaction (if any). |
amount string Read-only |
Amount related to the transaction operation (can be negative for a refund). |
currency string Read-only |
Currency of the operation. |
type string Read-only |
Type of the operation. Can be request , three_d_s_check , authorization , capture , void , refund , or chargeback . |
is_attempt boolean Read-only |
Denotes whether or not the operation is an attempt. |
has_failed boolean Read-only |
Denotes whether or not the operation has failed. Typically, has_failed will only be set when is_attempt is false (the operation only gets its results back after first attempting something). |
is_accountable boolean Read-only |
Denotes whether or not the amount of the operation should be used to compute the actual amount of the transaction. |
error_code string Read-only |
Operation error code, typically set when has_failed is true. |
error_message string Read-only |
Operation error message (null if the operation was successful). |
arn string Read-only |
Acquirer reference number. Use this to track a payment or refund with the issuer. |
gateway_operation_id string Read-only |
ID number assigned by the Payment Service Provider for the operation they performed. |
metadata Metadata dictionary |
Context related to the transaction’s invoice, key-value pair (string - string). |
created_at RFC1123 date or timestamp Read-only |
Date and time when this operation was created. |
Transaction status codes
The status
field of the Transaction
object contains a code that represents
the current status of the transaction. This gets updated automatically as the
transaction progresses (from authorization to capture, for example).
The table below shows all the status codes along with their meanings.
waiting | No payment has been placed yet. |
pending | The payment is pending confirmation by the payment gateway. |
authorized | The payment was authorized but has not yet been captured. |
pending-capture | The payment gateway initiated a capture, but it has not been confirmed yet. |
completed | The payment was successfully completed. |
failed | The payment was placed, but has failed |
voided | The payment was voided. |
refunded | The transaction was refunded (totally or partially). |
in-review | The transaction is pending fraud review. |
blocked | The transaction was blocked by your blocking rules or by a fraud review. |
retrieval-request | The payment was previously completed but the customer does not recognize the payment and is asking for information. |
fraud-notification | The payment was previously completed but the bank is notifying you that a chargeback might happen. |
chargeback-initiated | The payment was previously completed but the customer has filed a dispute against it. |
solved | The previous dispute has been resolved in your favor. |
reversed | The previous dispute has been resolved in your customer’s favor. |
Fetching a transaction
curl -X GET https://api.processout.com/transactions/tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newTransaction().find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC").then(
function(transaction) {
// Transaction was fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = client.new_transaction().find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
transaction = client.transaction.find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$transaction = $client->newTransaction()->find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
tr, err := client.NewTransaction().Find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC")
You can fetch a Transaction
object using its id
value. See the section about
fetching resources for more information.
Balances
Some payment providers allow customers to have a balance stored
on a Token
. An example of this is a gift card that has
a starting balance set when it is purchased. The recipient can
then spend the balance on one or more payments.
If the token is associated with payment providers that support APMs then you can use the server API to check the amount that that the customer has left on their balance.
Currently, the only balance method we support is vouchers
.
If the customer does not have any balance available then they can still pay
with one of the usual payment methods (card or APM).
Note that you should specify the amount
in the major unit of your
currency rather than the minor unit (so this would mean dollars rather
than cents if the currency is USD, for example).
Balance attributes
amount string Read-only |
Balance amount. |
currency string Read-only |
Balance currency. |
Balances attributes
vouchers list of Balance Read-only |
Contains all available vouchers and their values. |
Fetching Balances
curl -X GET https://api.processout.com/balances/tokens/tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
const ProcessOut = require("processout");
const client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// ...
const balances = await client.newBalances().find("tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy");
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# use customer payment token to retrieve any available balance
balances = client.new_balances().find("tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
# use customer payment token to retrieve any available balance
balances = client.balances.find("tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
// use customer payment token to retrieve any available balance
$balances = $client->newBalances()->find("tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy");
?>
import "github.com/processout/processout-go"
client := processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
// use customer payment token to retrieve any available balance
balances, err := client.NewBalances().Find("tok_fKK4btSG7wd13ZZaevzhMcuNbpjcu1Zy")
You can fetch the Balances
object for a token using the token’s
id
value. See the section about fetching resources
for more information.
Refunds
After a customer has made a payment on an invoice, you have the option to refund a part or the total of the amount they paid. It is usually easier to issue a refund from the Dashboard but you can also do it from the server API.
You can issue a full refund when the customer aborts or reverses a transaction (say by returning all the goods they purchased) but we also strongly recommend refunding any payment that you believe to be fraudulent. The reason is that Payment Service Providers (PSPs) will usually handle a refund for free but will impose a fee for a chargeback. If you do not refund the money then the victim of the fraud will most likely place a chargeback, which will cost you money.
A partial refund might be useful when a customer returns some of their purchase or otherwise reverses just a part of the transaction. However, you can also use a partial refund in place of a partial capture when the PSP does not support this. To do this, you can capture the payment in full and then refund the amount you would have left out of the partial capture.
Note that you should specify the amount
in the major unit of your
currency rather than the minor unit (so this would mean dollars rather
than cents if the currency is USD, for example).
Refund attributes
id string Read-only |
String value that uniquely identifies the refund. |
transaction transaction_id Transaction expandable |
Transaction for which the refund was issued. |
reason string Required |
Reason for the refund (customer_request , duplicate or fraud ). |
information string |
Extra information about the refund. |
amount string Required |
Refund amount applied to the transaction. |
has_failed boolean Read-only |
Denotes whether or not this refund failed asynchronously. |
metadata Metadata dictionary |
Metadata related to the refund, in the form of key-value pairs (string - string). |
sandbox boolean Read-only |
Denotes whether or not this refund was created in the sandbox testing environment. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this refund was created. |
invoice_detail_ids list of string |
List of invoice detail IDs for which the refund is made. |
Fetching a refund
curl -X GET https://api.processout.com/transactions/tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC/refunds/refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newRefund().find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH").then(
function(refund) {
// Refund was fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
refund = client.new_refund().find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
refund = client.refund.find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$refund = $client->newRefund()->find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
refund, err := client.NewRefund().Find("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"refd_QKliea9OGXtLBXcar2SJjfD11aY0J2SH")
You can fetch a Refund
object for a transaction using the transaction’s
id
value. See the section about fetching resources
for more information.
Issuing a refund
curl -X POST https://api.processout.com/transactions/tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC/refunds \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-d reason=customer_request \
-d amount=4.99
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newRefund().create({
transaction_id: "tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
reason: "customer_request",
amount: "4.99"
}).then(function(refund) {
//
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
refund = client.new_refund().create({
"transaction_id": "tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"reason": "customer_request",
"amount": "4.99"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
refund = client.refund.create(
transaction_id: "tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
reason: "customer_request",
amount: "4.99"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$refund = $client->newRefund()->create(array(
"transaction_id" => "tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC",
"reason" => "customer_request",
"amount" => "4.99"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
refund, err := client.NewRefund().Create(processout.RefundCreateParameters{
Refund: &processout.Refund{
TransactionID: processout.String("tr_ItJdKlhfaVn0SUGd9z1i9Jqe0STl4jxC"),
Reason: processout.String("customer_request"),
Amount: processout.String("4.99"),
},
})
You can issue a refund by creating a new Refund
object. This must reference
the transaction ID to be refunded and include a reason
(which can be
customer_request
, duplicate
or fraud
) and the amount
you want to
refund. You can make any number of partial refunds on the transaction but if
you omit the amount
field then any amount remaining is refunded in full.
Pass a list of id
strings in the invoice_detail_ids
field
to indicate which items from the invoice are being refunded. If you omit
this field then all items from the details
field of the Invoice
object
are included in the list.
Events
Below is an example of the content of the
data
field of an event.
{
"name": "transaction.captured",
"sandbox": false,
"transaction": {
"id": "tr_WZIEktoQtzflmfv4aJA645Qwj3JzaVGa",
"invoice_id": "iv_CKL1LOXGZ71wYAqGCyfDFhDTR3MGPkLY",
"invoice": {
"id":"proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"name":"T-Shirt Size M",
"price":"22.99",
"total":"22.99",
"currency":"USD",
"request_email":true,
"request_shipping":false,
"return_url":"https://sales.appgrouplimited.com",
"cancel_url":null,
"sandbox":false,
"url":"https://checkout.processout.com/iv_...",
"created_at":"2016-11-05T13:05:27.136003Z"
},
"customer_id": "cust_74qLxAbCpEYOxiBBwXTPKTP4QgTstude",
"customer":{
"id":"cust_74qLxAbCpEYOxiBBwXTPKTP4QgTstude",
"balance":"0",
"currency":"USD",
"email":"john@gmail.com",
"first_name":"",
"last_name":"",
"address1":"",
"address2":"",
"city":"",
"state":"",
"zip":"",
"country_code":"",
"metadata":{},
"sandbox":false,
"created_at":"2016-11-05T13:05:47.963398Z",
"transactions_count":1,
"mrr_local":0,
"total_revenues_local":22.99
},
"card_id": "card_knolIrMhVyZXLyYwZ56o6jxgYslH0Sqy",
"card": {
"address1": null,
"address2": null,
"avs_check": "unknown",
"cvc_check": "passed",
"bank_name": "",
"brand": "",
"city": null,
"country_code": "US",
"created_at": "2017-03-17T17:05:08.675622Z",
"exp_month": 10,
"exp_year": 2018,
"expires_soon": false,
"id": "card_knolIrMhVyZXLyYwZ56o6jxgYslH0Sqy",
"iin": "424242",
"last_4_digits": "4242",
"metadata": {},
"name": null,
"project_id": "9b66d6da-45e7-489f-bf91-0a012fe60490",
"sandbox": false,
"scheme": "visa",
"state": null,
"type": "credit",
"zip": null
},
"refunds": [],
"status": "completed",
"created_at": "2017-03-17T17:04:55.813311Z",
"amount": "22.99",
"authorized": true,
"authorized_amount": "22.99",
"available_amount": "22.99",
"captured": true,
"captured_amount": "22.99",
"refunded_amount": "0",
"currency": "EUR",
"details": {
"country": null
},
"error_code": null,
"estimated_fee": "0.57",
"gateway_fee": "0.51",
"gateway_fee_details": {
"exchange_fee": "0",
"processing_fee": "0.51",
"refund_fee": "0"
},
"gateway_name": "stripe",
"metadata": {},
"name": "T-Shirt Size M",
"sandbox": false
}
}
Your project creates (or “fires”) an Event
object for any significant
change in its status. This is particularly important
for updates to transactions but events are also fired for other
situations.
You can configure your project to send a notification message to a webhook whenever a new event is fired. The message is just an HTTP POST that contains the ID value of the new event. Use this ID to fetch the event and examine the data it contains.
An example of the data from an event is shown to the right. It is
essentially a copy of the resource object that the event concerns (so for
a transaction event, the data will be a copy of the Transaction
object that changed). The first level of sub-resources are
expanded automatically but you may need to
fetch other resources that are nested more deeply.
See the sections below for a full description of all the event types.
Event attributes
id string Read-only |
String value that uniquely identifies the refund. |
name string Read-only |
Name of the event (which corresponds to the action that happened). |
project project_id Project expandable |
Project that the event belongs to. |
data JSON object Read-only |
Data linked to the event (which is essentially a copy of the resource object that changed). |
sandbox boolean Read-only |
Denotes whether or not this event was created in the sandbox testing environment. |
fired_at RFC1123 date or timestamp Read-only |
Date and time when this event was fired. |
Fetching an event
curl -X GET https://api.processout.com/events/ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newEvent().find("ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb").then(
function(event) {
// We may now access the event
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
event = client.new_event().find("ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
event = client.event.find("ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$event = $client->newEvent()->find("ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
ev, err := client.NewEvent().Find("ev_T3wg9169RyGLnf1BIgTjLhrolEZU1DSb")
You can fetch an Event
object using its id
value. See the section about
fetching resources for more information.
Transaction events
A Transaction
object is returned whenever you authorize
or capture an invoice. The payment is often complete
at this point but there are cases where the data in the Transaction
can change after
it is initially created. For example, the customer may request a chargeback, which will
reverse the payment if it is successful. Also, if you authorize an invoice
to be captured automatically after a delay then you will not receive direct
confirmation that the payment was captured correctly. We recommend that you
listen for transaction events to handle cases like these.
The full set of transaction events is shown in the table below.
transaction.requested |
A payment request was made but no payment has been placed yet. |
transaction.authorized |
The payment has been authorized but is not available in your balance until you capture it. |
transaction.captured |
The payment has been captured and funds have been confirmed. |
transaction.failed |
The payment has failed. |
transaction.voided |
The transaction has been voided and cannot be captured anymore. |
transaction.refunded |
You issued a refund on the transaction. Use the refunded_amount field and also the refunds objects list to find the amount that was refunded. |
transaction.chargeback.created |
A chargeback has been filed by your customer. |
transaction.chargeback.won |
The previously filed chargeback was resolved in your favor. |
transaction.chargeback.lost |
The previously filed chargeback was resolved in your customer’s favor. |
transaction.chargeback.retrieval-request |
The payment was previously completed but the customer does not recognize it and is asking for information. |
transaction.chargeback.fraud-notification |
The payment was previously completed but the bank is notifying you that the customer might request a chargeback. |
transaction.operation.three-d-s.pending |
The payment’s 3DS check is pending. |
transaction.operation.three-d-s.failed |
The payment’s 3DS check failed. |
transaction.operation.three-d-s.success |
The payment passed the 3DS check. |
transaction.operation.three-d-s-2.pending |
The payment’s 3DS2 check is pending. |
transaction.operation.three-d-s-2.failed |
The payment’s 3DS2 check failed. |
transaction.operation.three-d-s-2.success |
The payment passed the 3DS2 check. |
Customer events
These events are fired when a Customer
object is
created, deleted, or updated.
customer.created |
A new customer resource was created. |
customer.updated |
A customer resource was updated. |
customer.deleted |
A customer resource was deleted. |
Customer token events
Customer token events are fired for creation, deletion, and updates but also when verification succeeds or fails.
customer.token.created |
A new customer token resource was created. |
customer.token.updated |
A customer token resource was updated. |
customer.token.deleted |
A customer token resource was deleted. |
customer.token.verified |
A customer token was verified successfully. |
customer.token.verification.failed |
A customer token verification failed. |
Payouts
It is important for you to be able to match transfers on your bank account statements with the transactions they include. This can be difficult because the actual money movement may happen a few days after you capture an invoice. Also, if you use several Payment Service Providers (PSPs) with Smart Router then it may not always be clear which PSP handled which transaction from the bank statement alone.
To make the task easier, ProcessOut will fetch reports from
your PSPs about money transfers whenever possible. We then match each
transfer with its corresponding transactions and create a Payout
object with all the details. (Note that a payout in this sense can
actually be a positive or a negative amount because refunds and
chargebacks are reported in the same way as payments.)
The Payout
object is designed to be a convenient abstraction of the different
reporting methods that PSPs use. Contact your ProcessOut account
manager if you need further details of how a particular PSP
reports their payouts to us.
For any fields that refer to an amount of money (such as amount
and
fees
), you should specify the amount in the major unit of the
currency rather than the minor unit (so this would mean dollars rather
than cents if the currency is USD, for example).
Note that because payouts involve genuine money transfers, they are not available when you are testing in sandbox mode.
Payout attributes
id string Read-only |
String value that uniquely identifies the payout. |
project project_id Project expandable |
Project that the payout belongs to. |
items list of PayoutItem expandable |
Items listed in the payout. |
status string Read-only |
Status of the payout. Can be pending , in-flight , received , canceled or failed . |
amount string Read-only |
Amount of the payout that was wired to your bank. |
currency string Read-only |
Currency of the payout. |
bank_name string Read-only |
Name of the bank to which the payout was issued, if available. |
bank_summary string Read-only |
Bank summary of the payout, if available. |
sales_transactions integer Read-only |
Number of transactions involved in this payout. |
sales_volume string Read-only |
Sum of the values of all transactions involved in this payout. |
refunds_transactions integer Read-only |
Number of refunds involved in this payout. |
refunds_volume string Read-only |
Sum of the values of all refunds involved in this payout. |
chargebacks_transactions integer Read-only |
Number of chargebacks involved in this payout. |
chargebacks_volume string Read-only |
Sum of the values of all chargebacks involved in this payout. |
metadata Metadata dictionary |
Metadata related to the payout, in the form of key-value pairs (string - string). |
fees string Read-only |
Fees taken by the PSP. |
adjustments string Read-only |
Adjustments applied by the PSP to the final payout amount. |
reserve string Read-only |
Reserve kept by the PSP for the payout. |
settled_at RFC1123 date or timestamp Read-only |
Date and time when this payout was settled. |
created_at RFC1123 date or timestamp Read-only |
Date and time when this payout was created. |
PayoutItem attributes
id string Read-only |
String value that uniquely identifies the payout item. |
project project_id Project expandable |
Project that the payout item belongs to. |
payout payout_id Payout expandable |
Payout that the payout item belongs to. |
transaction transaction_id Transaction expandable |
Transaction involved in this payout item. Can be null if the item is not linked to a particular transaction, or if it is a transaction that was not handled by ProcessOut. |
type string Read-only |
Type of the payout item. Can be sale , refund , chargeback , fee , adjustment , reserve . |
gateway_resource_id string Read-only |
ID used by the PSP to reference this payout item. |
amount string Read-only |
Amount of the payout item (can be negative for a refund). |
fees string Read-only |
Fees taken on this specific payout item. |
metadata Metadata dictionary Read-only |
Context related to the payout item, key-value pair (string - string) |
created_at RFC1123 date or timestamp Read-only |
Date and time when this payout item was created. |
Fetching a payout
curl -X GET https://api.processout.com/payouts/payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newPayout().find("payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH").then(
function(payout) {
// The payout was fetched
}, function(err) {
// The payout could not be found
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payout = client.new_payout().find("payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH")
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payout = client.payout.find("payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH")
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$payout = $client->newPayout()->find("payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH");
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
payout, err := client.NewPayout().Find("payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH")
You can fetch a Payout
object using its id
value. See the section about
fetching resources for more information.
Listing payouts
curl -X GET -G https://api.processout.com/payouts \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
--data-urlencode limit=20 \
--data-urlencode order=asc
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
client.newPayout().all({
limit: 20,
order: "asc"
}).then(function(payouts) {
// Payouts were fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payouts = client.new_payout().all({
"limit": 20,
"order": "asc"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payouts = client.payout.all(
limit: 20,
order: "asc"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$payouts = $client->newPayout()->all(array(
"limit" => 20,
"order" => "asc"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
payouts, err := client.NewPayout().All(processout.PayoutAllParameters{
Options: &processout.Options{
Limit: 20,
Order: "asc",
},
})
You can list all payouts in your project with the all()
function. See
the section about listing resources to learn how to
access the list in stages using pagination.
Listing payout items
curl -X GET https://api.processout.com/payouts/payt_3vfLtjoiQxpXZrdd6dc8Qgxxe26vy0aH/items \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
--data-urlencode limit=20 \
--data-urlencode order=asc
var ProcessOut = require("processout");
var client = new ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
payout.fetchItems({
limit: 20,
order: "asc"
}).then(function(payoutItems) {
// Payout items were fetched
}, function(err) {
// An error occured
});
import processout
client = processout.ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payout_items = payout.fetch_items()({
"limit": 20,
"order": "asc"
})
require "processout"
client = ProcessOut::Client.new(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB")
payout_items = payout.fetch_items(
limit: 20,
order: "asc"
)
<?php
$client = new \ProcessOut\ProcessOut(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB");
$payoutItems = $payout->fetchItems(array(
"limit" => 20,
"order" => "asc"
));
import "github.com/processout/processout-go"
var client = processout.New(
"test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x",
"key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB",
)
payoutItems, err := payout.FetchItems(processout.PayoutFetchItemsParameters{
Options: &processout.Options{
Limit: 20,
Order: "asc",
},
})
If you expand the items
field of a Payout
object then you will see only the first few items. Use the fetchItems()
function to get a list of all items. Note that this function supports
pagination to let you manage the list easily.
Analytics/Monitoring
Ingesting transaction data
As well as the payment API, ProcessOut also provides tools to help merchants analyze, benchmark and monitor the performance of their payments. See the page about the Telescope product on our main website for more information.
ProcessOut connects directly to your PSPs to retrieve your transactions for analysis where possible. This does not normally require any technical integration or change from your side but you may still sometimes need to supply us with transaction data directly using our API. For example, even if a particular Payment Service Provider (PSP) does not give us direct access to their data, you can still supply that data yourself for analysis.
Pushing data
curl -X POST https://api.processout.com/handlers/ingest-transactions/gway_conf_9ie0prejnta3p9l2ns9030fiphlra7sz \
-u test-proj_gAO1Uu0ysZJvDuUpOGPkUBeE3pGalk3x:key_sandbox_mah31RDFqcDxmaS7MvhDbJfDJvjtsFTB \
-H "Content-Type: application/json" \
-d @- << EOF
{
"transactions": [{
"id": "your-transaction-id",
"customer": {
"id": "your-customer-id",
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"address1": "23 rue de Strasbourg",
"address2": "1e etage",
"city": "Paris",
"state": "",
"zip": "75001",
"country_code": "FR",
"ip_address": "127.0.0.1",
"metadata": {
"custom_field": "with whatever data you want"
},
"created_at": "2009-11-10T23:00:00Z"
},
"new_operation": {
"id": "your-operation-id",
"card": {
"id": "your-card-id",
"iin": "424242",
"last_4_digits": "4242",
"exp_month": 12,
"exp_year": 2020,
"name": "Cardholder name",
"metadata": {
"custom_field": "with whatever data you want"
},
"created_at": "2009-11-10T23:00:00Z"
},
"amount": "12.90",
"has_failed": false,
"type": "authorization",
"metadata": {
"custom_field": "with whatever data you want"
},
"raw_error_code": "05",
"raw_error_code_norm": "sips",
"payment_type": "card",
"acquirer_name": "societe generale",
"eci": "05",
"mcc": "5734",
"merchant_account_id": "your-merchant-id",
"cvc_check": "passed",
"avs_postal_check": "passwed",
"avs_street_check": "unavailable",
"avs_name_check": "unavailable",
"three_d_s_check": "passed",
"created_at": "2009-11-10T23:00:00Z"
},
"name": "Your transaction name/ID",
"currency": "EUR",
"metadata": {
"custom_field": "with whatever data you want"
},
"created_at": "2009-11-10T23:00:00Z"
}]
}
EOF
You can use a tool such as curl
to access our ingestion
endpoint but we do not currently provide SDKs for it.
You can see a sample of some data for ingestion in the panel to the right.
The JSON payload appears quite large but the format is straightforward
and some items of data are optional. Note that the data objects for
ingestion (such as Transaction
and Operation
) are not identical
to the objects with the same names from the main server API. When you are
preparing data for ingestion, you should refer to the object descriptions
below in this section.
There are a few things to note about using the ingestion endpoint:
- The transaction data will be linked to the gateway configuration ID that you specify in the URL. If you are using more than one PSP then you must create a gateway configuration for each of them.
- The overall amount for the transaction is not stored in the JSON data. It will be calculated from the amounts specified in the individual operations that you push.
- Some of the data fields are marked as required but the others are optional. However, we recommend that you supply as many data fields as you can. The more data you supply, the better the analysis will be.
- You should add the exact error code and norm returned by the PSP in the
raw_error_code
andraw_error_code_norm
fields. We may not be able to parse these fields if you have modified their values in any way.
Transaction attributes for ingestion
id string Required |
Your internal unique ID for the transaction. |
name string Required |
Name of the transaction. This could be its bank statement dynamic descriptor, for example. |
currency string Required |
Currency of the transaction, in ISO 4217 format (for example, USD ).Must be a valid ISO 4217 currency code with 3 characters |
new_operation Operation Required |
New operation processed on this transaction (such as an authorization or a refund). |
customer Customer |
Customer object to which this transaction is linked. Not required, but strongly recommended if available. |
metadata Metadata dictionary |
Metadata related to the transaction, in the form of key-value pairs (string - string). |
created_at RFC1123 date or timestamp |
Date and time when the transaction was created. |
Operation attributes for ingestion
id string Required |
Your internal unique ID for the operation. |
card Card Required if the payment_type is card |
Card object. |
type string Required |
Type of the operation. Can be authorization , capture , void , refund , or chargeback . |
amount string Required |
Amount of the operation, in the currency of the transaction. |
has_failed boolean Required |
This is true if the operation failed (for example, if an authorization was declined) and false otherwise. |
raw_error_code string Required if has_failed is true |
The raw error code returned by your PSP, such as 05 for SIPS. You should not send a modified version of the error code because we may not be able to parse it. |
raw_error_code_norm string Required if has_failed is true |
Norm of the error code (which is the kind of PSP that generated the error code). Currently supported norms are french_bank , payline , sips , and hipay . Contact us if you need one that is not listed here. |
payment_type string Required |
Type of the payment. Can be card , three-d-s , paypal , vpay , sepa , ideal , sofort , apple-pay , bancontact , or android-pay . |
acquirer_name string |
Acquirer used to process the transaction (such as societe generale ). |
merchant_account_id string |
ID of the merchant account used to process the transaction. You can supply this in any format. |
eci string |
ECI (Electronic Commerce Indicator) used to process the transaction (also known as ERT in France). An example value is 05 for a non-3DS transaction. |
mcc string |
MCC (Merchant Category Code) used to process the transaction. An example value is 5734 for SaaS businesses. |
cvc_check string |
Status of the CVC check, if known. Can be passed , failed , unavailable , unchecked , unknown , or required . Here, unavailable means the CVC was not available to be sent to the PSP, whereas unchecked means it was available but was not used to process the check. Also, required means the CVC was not available but was required by the bank to accept the transaction. |
avs_postal_check string |
Status of the AVS postal check, if known. Contains the same type of value as cvc_check above. |
three_d_s_check string |
Status of the 3DS check performed on the transaction, if any. Can be passed or failed . If left empty, it means the transaction was not authenticated using 3DS. |
metadata Metadata dictionary |
Metadata related to the operation, in the form of key-value pairs (string - string). |
created_at RFC1123 date or timestamp |
Date and time when the operation was created. |
Customer attributes for ingestion
id string Required |
Your internal unique ID for the customer. |
email string |
Email of the customer. |
first_name string |
First name of the customer. |
lasts_name string |
Last name of the customer. |
address1 string |
First line of the customer’s address. |
address2 string |
Second line of the customer’s address. |
city string |
City of the customer’s address. |
state string |
State of the customer’s address, if applicable. |
zip string |
ZIP or postal code of the customer’s address. |
country_code string |
Country code (US , FR …) of the customer’s address.Must be a valid ISO 3166 country code with 2 characters |
ip_address string |
IP address of the customer. |
metadata Metadata dictionary |
Metadata related to the customer, in the form of key-value pairs (string - string). |
created_at RFC1123 date or timestamp |
Date and time when the customer was created. |
Card attributes for ingestion
id string Required |
Your internal unique ID for the card or token. |
iin string Required |
IIN of the card (which is the first 6 digits of the main card number). Also known as BIN. |
last_4_digits string |
Last 4 digits of the card, if available. |
exp_month integer Required |
Expiration month of the card. |
exp_year integer Required |
Expiration year of the card, using 4 digits (“2023” instead of just “23”). |
name string |
Cardholder name (if one was used to submit the transaction). |
metadata Metadata dictionary |
Metadata related to the card, in the form of key-value pairs (string - string). |
created_at RFC1123 date or timestamp |
Date and time when the card was created. |