Send an Order
Call /v1/order after a customer completes checkout. Pinch records the order, updates the customer's variables, runs the Orders workflow, and returns a decision (ALLOW, DENY, REVIEW) along with the abuse score.
Most fields below are optional in the schema but make Pinch's scoring substantially more accurate. Required for a useful score: order ID, totals, line items, customer email, payment info, and device fingerprint if available.
Request
POST /v1/order HTTP/1.1
Host: api.pinch.ai
Authorization: {api-key}
Content-Type: application/json
Body
| Field | Type | Required | Description |
|---|---|---|---|
intent | string | yes | Always Order for a placed order. |
state | string | yes | One of PAID, AUTHORIZED, PENDING. |
providerCartId | string | no | Your platform's cart identifier. |
providerOrderId | string | yes | Your platform's order identifier — must be unique. |
totalPrice | object | yes | { currencyCode, amount }. Currency is ISO 4217 numeric (840 = USD). |
totalTaxes | object | no | Same shape as totalPrice. |
totalShippingPrice | object | no | Same shape as totalPrice. |
totalDiscounts | array | no | Array of { amount }. |
lineItems | array | yes | See lineItems. |
customer | object | yes | See customer. |
merchant | object | no | See merchant. |
paymentInfo | array | yes | See payment info. |
deviceFingerprints | array | recommended | See device fingerprints. |
customData | object | no | Free-form key/value for merchant-specific data. |
timestamp | string | yes | Epoch ms as a string. |
Line items
Each entry in lineItems:
| Field | Type | Required | Description |
|---|---|---|---|
identifiers | array | yes | One or more { identifierType, identifier }. Identifier types: UPC, EAN, JAN, SKU, SerialNo. |
title | string | yes | Product title. |
category | string | yes | Product category. |
brand | string | no | Product brand. |
colour | string | no | Color variant. |
size | string | no | Size variant. |
quantity | string | yes | Quantity as a string. |
unitPrice | object | yes | { currencyCode, amount }. |
discounts | array | no | Array of discounts applied to this line. |
Customer
| Field | Type | Required | Description |
|---|---|---|---|
firstName | string | yes | |
lastName | string | yes | |
fullName | string | no | If provided, takes precedence. |
contactInformation | array | yes | Array of contact entries. |
Each contactInformation entry has a contactType of ContactAddress, EMail, or Phone:
ContactAddress—{ address: { line1, line2, city, state, postalCode, country, geoCode: { longitude, latitude } }, addressType: "Billing" \| "Shipping" \| "Business" }EMail—{ address: "..." }Phone—{ number: "+1..." }
At minimum, send one EMail and one ContactAddress of type Billing or Shipping.
Merchant
| Field | Type | Description |
|---|---|---|
brand | string | Brand or store name. |
providerMerchantId | string | Your platform's merchant identifier. |
locationInfo | object | Optional store location. |
Payment info
Each entry in the paymentInfo array:
| Field | Type | Description |
|---|---|---|
amount | object | { currencyCode, amount }. |
instrument | string | e.g. CC-A, DC-A, GiftCard. |
last4 | string | Last 4 digits of the card. |
BIN | string | Bank Identification Number. |
paymentIdentifier | string | Your platform's payment identifier. |
postalCode | string | Billing postal code on the payment instrument. |
method | string | NotPresent, Swipe, Tap, Dip. |
auth | string | Authorization code. |
AID | string | Application ID (EMV). |
giftCardUsed | string | "True" or "False". |
loyalty_membership | string | "True" or "False". |
cvv_result_code | string | Processor CVV result. |
avs_result_code | string | Processor AVS result. |
paymentStatus | string | pre-auth success, captured, etc. |
expiry | string | MM/YY. |
Device fingerprints
[
{ "deviceIdentifier": "{visitorId}" }
]
visitorId comes from the Device JS SDK. Retrieve it from localStorage at checkout and forward to your server, then include it here. Strongly recommended — device signals account for a substantial share of Pinch's scoring.
Example request
- curl
- Node
- Python
curl https://api.pinch.ai/v1/order \
-H "Authorization: {api-key}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"intent": "Order",
"state": "PAID",
"providerOrderId": "MC229151G",
"totalPrice": { "currencyCode": "840", "amount": "239.0" },
"lineItems": [
{
"identifiers": [{ "identifierType": "UPC", "identifier": "26SDSDSMC30" }],
"title": "Maxi Dress Floral",
"category": "Dress",
"brand": "Demo Brand",
"colour": "blue",
"size": "M",
"quantity": "1",
"unitPrice": { "currencyCode": "840", "amount": "239.0" },
"discounts": []
}
],
"customer": {
"firstName": "John",
"lastName": "Doe",
"fullName": "John Doe",
"contactInformation": [
{ "contactType": "EMail", "address": "johndoe@example.com" },
{
"contactType": "ContactAddress",
"address": {
"line1": "1234 Main St",
"city": "San Francisco",
"state": "CA",
"postalCode": "94101",
"country": "US"
},
"addressType": "Shipping"
}
]
},
"paymentInfo": [
{
"amount": { "currencyCode": "840", "amount": "239.0" },
"instrument": "CC-A",
"last4": "4532",
"BIN": "282739",
"postalCode": "94101",
"method": "NotPresent",
"paymentStatus": "pre-auth success",
"expiry": "04/27"
}
],
"deviceFingerprints": [{ "deviceIdentifier": "abc123visitorId" }],
"timestamp": "1720791715000"
}'
const response = await fetch("https://api.pinch.ai/v1/order", {
method: "POST",
headers: {
"Authorization": process.env.PINCH_API_KEY,
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
intent: "Order",
state: "PAID",
providerOrderId: "MC229151G",
totalPrice: { currencyCode: "840", amount: "239.0" },
lineItems: [/* ... */],
customer: {/* ... */},
paymentInfo: [/* ... */],
deviceFingerprints: [{ deviceIdentifier: visitorId }],
timestamp: String(Date.now())
})
});
const decision = await response.json();
import os, requests, time
response = requests.post(
"https://api.pinch.ai/v1/order",
headers={
"Authorization": os.environ["PINCH_API_KEY"],
"Content-Type": "application/json",
"Accept": "application/json",
},
json={
"intent": "Order",
"state": "PAID",
"providerOrderId": "MC229151G",
"totalPrice": {"currencyCode": "840", "amount": "239.0"},
"lineItems": [...],
"customer": {...},
"paymentInfo": [...],
"deviceFingerprints": [{"deviceIdentifier": visitor_id}],
"timestamp": str(int(time.time() * 1000)),
},
)
decision = response.json()
Response
{
"providerOrderID": "MC229151G",
"pinchOrderID": "pin_8c2f9a1b",
"cartLevelDecisions": [
{
"providerCartID": "54154079438549",
"pinchCartID": "pcart_1f9d",
"decisions": [
{
"decisionType": "APPROVE/DECLINE",
"decision": "APPROVE",
"subDecision": "Default Approve",
"decisionReason": "No risk signals detected",
"abuseScore": 12
}
]
}
]
}
| Field | Description |
|---|---|
providerOrderID | Echo of your providerOrderId. |
pinchOrderID | Pinch's internal order identifier. |
cartLevelDecisions[].decisions[].decision | APPROVE, DECLINE, or REVIEW. |
cartLevelDecisions[].decisions[].subDecision | The specific branch that matched in your workflow. |
cartLevelDecisions[].decisions[].decisionReason | Human-readable explainer. |
cartLevelDecisions[].decisions[].abuseScore | 0–100 abuse risk score. |
Errors
See Errors for the full error envelope. Common error codes for this endpoint:
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Missing required field or malformed JSON. |
| 401 | unauthenticated | API key missing or invalid. |
| 409 | duplicate_order | providerOrderId already exists for this merchant. |
| 422 | unprocessable_entity | Field values failed validation (e.g. unknown currency code). |
| 429 | rate_limited | Slow down. |
| 500 | internal_error | Retry with exponential backoff. |
Idempotency
Pinch treats providerOrderId as the idempotency key. Retrying the same providerOrderId returns the original decision rather than creating a duplicate. See Conventions for more.
See also
- Returns API — submit a return for the same order
- Decisions — what
decisionandsubDecisionmean