NAV Navbar

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 is https://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 the limit value that you specify).
  • has_more: This is false when you use start_after and the page contains the last item in the list or when you use end_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 call all() with a limit value of 1 and ignore the page array if you only want to find the total_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. Use capture_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. Set capture_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. Set invoice_detail_ids with an array that contains the id values of the InvoiceDetail objects that you want to include. If you omit this option (or the PSP does not support it) then the full list from the details 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 and raw_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.
>_