Skip to main content

Sale Orders

Initiate Publica.la's checkout flow where customers pay directly through the platform. Orders start with pending status and transition to approved after successful payment via integrated payment gateways (Stripe, MercadoPago, etc.).

See Choosing the Right Order Type for guidance on when to use sale orders.


Creating a Sale Order

Endpoint

POST /api/v3/orders

Request Body

{
"type": "sale",
"external_id": "CART-12345",
"return_url": "https://yoursite.com/thank-you",
"unit_price": 29.99,
"currency_id": "USD",
"user": {
"id": "customer-123",
"email": "[email protected]"
},
"products": [
{
"type": "content",
"external_id": "9781234567890",
"unit_price": 29.99,
"currency_id": "USD"
}
]
}

Required Fields

FieldTypeDescription
typestringMust be "sale"
return_urlstringURL to redirect after payment
unit_pricefloatTotal order amount
currency_idstringISO 4217 currency code
userobjectUser information
user.idstringUser external ID (required)
productsarrayProducts in the order
products[].typestringcontent or subscription
products[].external_idstringProduct external ID
products[].unit_pricefloatIndividual product price
products[].currency_idstringProduct currency

Optional Fields

FieldTypeDescription
external_idstringYour unique order ID (max 64 chars)
user.emailstringUser email address
products[].namestringProduct name (required for auto-creation)
products[].urlstringExternal URL (required for auto-creation)

External Content (Auto-Creation)

If you're selling content hosted outside Publica.la, you can create sale orders without pre-registering the product. When a products[].external_id doesn't exist, the system automatically creates a link-type product using the provided name and url.

This is useful when:

  • Content is hosted on your own platform
  • You want to track sales in Publica.la without uploading the actual content
  • You need to maintain order history for external resources

Example: External Content Sale

curl -X POST "https://yourstore.publica.la/api/v3/orders" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "sale",
"return_url": "https://yourstore.com/confirmation",
"unit_price": 19.99,
"currency_id": "USD",
"user": {
"id": "user-123"
},
"products": [
{
"external_id": "EXTERNAL-COURSE-001",
"type": "content",
"name": "Advanced Photography Course",
"url": "https://yourplatform.com/courses/photography",
"unit_price": 19.99,
"currency_id": "USD"
}
]
}'

The product will be created with external_id: "EXTERNAL-COURSE-001" and readers will be redirected to the provided URL.


Request Examples

Basic Sale Order (USD - Stripe)

curl -X POST "https://yourstore.publica.la/api/v3/orders" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "sale",
"external_id": "WEB-ORDER-12345",
"return_url": "https://yourstore.com/order/confirmation",
"unit_price": 29.99,
"currency_id": "USD",
"user": {
"id": "user-ext-789",
"email": "[email protected]"
},
"products": [
{
"external_id": "PREMIUM-EBOOK",
"type": "content",
"unit_price": 29.99,
"currency_id": "USD"
}
]
}'

Sale Order (ARS - MercadoPago)

curl -X POST "https://yourstore.publica.la/api/v3/orders" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "sale",
"external_id": "ARS-ORDER-789",
"return_url": "https://yourstore.com/gracias",
"unit_price": 5000.00,
"currency_id": "ARS",
"user": {
"id": "user-ar-456",
"email": "[email protected]"
},
"products": [
{
"external_id": "LIBRO-DIGITAL",
"type": "content",
"unit_price": 5000.00,
"currency_id": "ARS"
}
]
}'

Sale Order with Subscription

curl -X POST "https://yourstore.publica.la/api/v3/orders" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "sale",
"external_id": "SUB-ORDER-456",
"return_url": "https://yourstore.com/subscription/welcome",
"unit_price": 9.99,
"currency_id": "USD",
"user": {
"id": "user-sub-123",
"email": "[email protected]"
},
"products": [
{
"external_id": "MONTHLY-PREMIUM",
"type": "subscription",
"unit_price": 9.99,
"currency_id": "USD"
}
]
}'

Sale Order with Multiple Products

curl -X POST "https://yourstore.publica.la/api/v3/orders" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "sale",
"external_id": "CART-BUNDLE-001",
"return_url": "https://yourstore.com/checkout/complete",
"unit_price": 49.97,
"currency_id": "USD",
"user": {
"id": "user-cart-123",
"email": "[email protected]"
},
"products": [
{
"external_id": "EBOOK-001",
"type": "content",
"unit_price": 19.99,
"currency_id": "USD"
},
{
"external_id": "EBOOK-002",
"type": "content",
"unit_price": 14.99,
"currency_id": "USD"
},
{
"external_id": "EBOOK-003",
"type": "content",
"unit_price": 14.99,
"currency_id": "USD"
}
]
}'

Response

Success Response (201 Created)

{
"data": {
"id": "12345",
"uuid": "4db50ffb-80fd-42b1-9bdb-c572e1a5487f",
"external_id": "WEB-ORDER-12345",
"type": "sale",
"status": "pending",
"unit_price": 29.99,
"currency_id": "USD",
"created_at": "2025-12-03T22:44:07.000000Z",
"updated_at": "2025-12-03T22:44:07.000000Z"
}
}
Pending Status

Sale orders are created with status: pending. The order transitions to approved only after the user completes payment.

Response with Checkout URL

Request the checkout URL with ?include=pending_checkout:

{
"data": {
"id": "12345",
"uuid": "4db50ffb-80fd-42b1-9bdb-c572e1a5487f",
"external_id": "WEB-ORDER-12345",
"type": "sale",
"status": "pending",
"unit_price": 29.99,
"currency_id": "USD",
"created_at": "2025-12-03T22:44:07.000000Z",
"updated_at": "2025-12-03T22:44:07.000000Z",
"pending_checkout": {
"url": "https://yourstore.publica.la/auth/token?external-auth-token=eyJ0eXAiOiJKV1QiLCJhbGc...",
"ttl": 3600
}
}
}

Checkout Object Fields

FieldTypeDescription
pending_checkout.urlstringRedirect user here to complete payment
pending_checkout.ttlintegerSeconds until URL expires (typically 3600 = 1 hour)
Checkout URL

You MUST redirect the user to pending_checkout.url to complete the payment. The URL contains an authentication token that expires after the TTL period.


Checkout Flow

1. Your App                    2. Publica.la                3. Payment Gateway
| | |
|--- POST /api/v3/orders ----->| |
|<--- pending_checkout.url ----| |
| | |
|--- Redirect user ----------->| |
| |--- Payment redirect -------->|
| | |
| |<--- Payment callback --------|
| | |
|<--- Redirect to return_url --| |
| | |
|--- GET /api/v3/orders/{id} ->| |
|<--- status: approved --------| |

Flow Steps

  1. Create order via API
  2. Receive pending_checkout.url in response
  3. Redirect user to pending_checkout.url
  4. User completes payment through gateway
  5. User redirected to your return_url
  6. Verify order status via API

Return URL Parameters

After payment, user is redirected to your return_url with query parameters:

https://yourstore.com/thank-you?order_id=4db50ffb-80fd-42b1-9bdb-c572e1a5487f&status=approved
ParameterDescription
order_idPublica.la order UUID
statusOrder status (approved, pending, or cancelled)

Payment Gateways

The payment gateway is automatically selected based on currency_id:

CurrencyGatewaySupported Countries
USDStripeGlobal
EURStripeGlobal
ARSMercadoPagoArgentina
MXNMercadoPagoMexico
BRLMercadoPagoBrazil
CLPFlow (via MercadoPago)Chile
COPPayUColombia
Gateway Configuration

Gateway availability depends on your tenant configuration. Contact support if you need to enable specific gateways.


Order Status Lifecycle

  [Create] ─────► pending ──────[User Pays]──────► approved
│ │
└──────[Expires/Cancel]──────► cancelled
StatusDescription
pendingOrder created, awaiting payment
approvedPayment successful, user has access
cancelledOrder cancelled or payment failed

Managing Sale Orders

Check Order Status

curl -X GET "https://yourstore.publica.la/api/v3/orders/4db50ffb-80fd-42b1-9bdb-c572e1a5487f" \
-H "X-User-Token: your-api-token"

List Pending Orders

curl -X GET "https://yourstore.publica.la/api/v3/orders?filter[type]=sale&filter[status]=pending" \
-H "X-User-Token: your-api-token"

Get Checkout URL for Pending Order

If you need to resend the checkout URL:

curl -X GET "https://yourstore.publica.la/api/v3/orders/4db50ffb-80fd-42b1-9bdb-c572e1a5487f?include=pending_checkout" \
-H "X-User-Token: your-api-token"

Update Approved Order Expiration

Once approved, you can update expiration:

curl -X PUT "https://yourstore.publica.la/api/v3/orders/4db50ffb-80fd-42b1-9bdb-c572e1a5487f" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"expiration_date": "2026-12-31"
}'

Cancel Order

curl -X DELETE "https://yourstore.publica.la/api/v3/orders/4db50ffb-80fd-42b1-9bdb-c572e1a5487f" \
-H "X-User-Token: your-api-token" \
-H "Content-Type: application/json" \
-d '{
"reason": "Customer requested cancellation"
}'

Email Notifications

Automatic Notifications

When a sale order is successfully paid and approved, an email notification is automatically sent to the user confirming their purchase and providing access details. To disable automatic emails, go to your dashboard at /dashboard/settings#notifications.


Error Handling

Common Errors

StatusErrorCause
401UnauthenticatedInvalid or missing API token
404Product not foundProduct external ID doesn't exist
422user.id requiredSale orders require user.id
422user.email requiredSale orders require user.email
422Currency mismatchProduct currencies don't match order currency
422Invalid currencyCurrency not supported or gateway not configured

Error Response Example

{
"message": "The given data was invalid.",
"errors": {
"user.id": ["The user.id field is required."],
"user.email": ["The user.email field is required."]
}
}

Best Practices

  1. Store checkout URLs - Cache the checkout URL in case user needs to retry
  2. Verify status - Always verify order status after return, don't trust URL params alone
  3. Handle expiration - Checkout URLs expire; be prepared to request a new one
  4. Set appropriate return_url - Include order ID in return URL for easy lookup

See Also


X

Graph View