Skip to main content

PayPal

Learn how to automate PayPal operations using Abstra connectors through practical, focused tutorials.

API Behavior

run_connection_action() returns the data directly and automatically raises an exception if an error occurs. You don't need to check for status == "success" - just use try/except for error handling.

Getting Started

Prerequisites

  • PayPal Business account
  • PayPal Developer account access
  • API credentials (Client ID and Secret)
  • Abstra project

Quick Setup

  1. Go to PayPal Developer Dashboard
  2. Create an app (e.g., "Abstra Integration")
  3. Get your credentials (Client ID and Secret)
  4. Add PayPal connector in Abstra Console
  5. Enter your credentials and select environment:
    • Sandbox: For testing (fake money)
    • Production: For live transactions (real money)

Test your connection:

from abstra.connectors import run_connection_action

# List invoices
result = run_connection_action(
"paypal",
"invoicing/get_v2_invoicing_invoices"
)
print(f"✓ Connection works! Found {len(result['items'])} invoices")

🧾 Invoice Tutorials

Learn how to manage invoices in PayPal:

1. Listing and Searching Invoices

Find and filter invoices using various criteria.

You'll learn:

  • List all invoices
  • Filter by status (PAID, SENT, DRAFT)
  • Search by date range
  • Filter by customer email
  • Pagination for large datasets
# Quick example
result = run_connection_action("paypal", "invoicing/get_v2_invoicing_invoices")
invoices = result["items"]

# Filter paid invoices
paid = [inv for inv in invoices if inv["status"] == "PAID"]
print(f"Found {len(paid)} paid invoices")

2. Getting Invoice Details and Transactions

Retrieve complete invoice information including payment transactions.

You'll learn:

  • Get invoice by ID
  • View transaction details (payment ID, date, method)
  • Check payment status
  • Extract customer information
  • Get invoice items and amounts
# Quick example
invoice_id = "INV2-XXXX-XXXX-XXXX-XXXX"
result = run_connection_action("paypal",
"invoicing/get_v2_invoicing_invoices_by_invoice_id",
params={"invoice_id": invoice_id}
)

invoice = result
print(f"Invoice: {invoice['detail']['invoice_number']}")
print(f"Amount: ${invoice['amount']['value']}")

Common Patterns

List and Process Pattern

from abstra.connectors import run_connection_action

# 1. List all invoices
result = run_connection_action("paypal", "invoicing/get_v2_invoicing_invoices")
invoices = result["items"]

# 2. Process each invoice
for invoice in invoices:
if invoice["status"] == "PAID":
# Get detailed information
detail = run_connection_action(
"paypal",
"invoicing/get_v2_invoicing_invoices_by_invoice_id",
{"invoice_id": invoice["id"]}
)
# ... process invoice details

Filter and Aggregate Pattern

from abstra.connectors import run_connection_action
from collections import defaultdict

# Get all invoices
result = run_connection_action("paypal", "invoicing/get_v2_invoicing_invoices")
invoices = result["items"]

# Group by customer
customers = defaultdict(lambda: {"count": 0, "total": 0.0})

for inv in invoices:
if inv["status"] == "PAID":
email = inv["primary_recipients"][0]["billing_info"]["email_address"]
customers[email]["count"] += 1
customers[email]["total"] += float(inv["amount"]["value"])

# Display results
for email, data in customers.items():
print(f"{email}: {data['count']} invoices, ${data['total']:.2f}")

Search and Export Pattern

import csv
from abstra.connectors import run_connection_action

# Get invoices
result = run_connection_action("paypal", "invoicing/get_v2_invoicing_invoices")
invoices = result["items"]

# Export to CSV
with open("invoices.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["Invoice Number", "Status", "Amount", "Customer"])

for inv in invoices:
writer.writerow([
inv["detail"]["invoice_number"],
inv["status"],
inv["amount"]["value"],
inv["primary_recipients"][0]["billing_info"]["email_address"]
])

Quick Reference

Invoice Operations

ActionPurposeKey Parameters
invoicing/get_v2_invoicing_invoicesList all invoicesNone (optional: pagination)
invoicing/get_v2_invoicing_invoices_by_invoice_idGet invoice detailsinvoice_id
invoicing/get_v2_invoicing_templatesList invoice templatesNone

Order Operations

ActionPurposeKey Parameters
checkout_orders/get_v2_checkout_orders_by_idGet order detailsid

Subscription Operations

ActionPurposeKey Parameters
billing_subscriptions/get_v1_billing_plansList billing plansNone
billing_subscriptions/get_v1_billing_plans_by_idGet plan detailsid
billing_subscriptions/get_v1_billing_subscriptions_by_idGet subscription detailsid

Payment Operations

ActionPurposeKey Parameters
payments_payment/get_v2_payments_captures_by_capture_idGet capture detailscapture_id
payments_payment/get_v2_payments_refunds_by_refund_idGet refund detailsrefund_id

Invoice Status Values

StatusDescription
DRAFTInvoice created but not sent
SENTInvoice sent to customer
PAIDInvoice fully paid
MARKED_AS_PAIDManually marked as paid
CANCELLEDInvoice cancelled
REFUNDEDInvoice refunded
PARTIALLY_PAIDInvoice partially paid

Order Status Values

StatusDescription
CREATEDOrder created
SAVEDOrder saved (not completed)
APPROVEDOrder approved by customer
VOIDEDOrder voided
COMPLETEDOrder completed

Best Practices

Environment Management

# ✅ Always specify environment in connector config (in Abstra Console)
# Sandbox for testing, Production for live data

# ✅ Test with Sandbox connection first
result = run_connection_action("paypal-sandbox", "invoicing/get_v2_invoicing_invoices")

# Production only for read operations
result = run_connection_action("paypal-production", "invoicing/get_v2_invoicing_invoices")

Error Handling

# ✅ Use try/except - run_connection_action raises exception on error
try:
invoices = run_connection_action("paypal", "invoicing/get_v2_invoicing_invoices")
# invoices is the data object with {"items": [...], "links": [...]}
for invoice in invoices["items"]:
print(invoice["detail"]["invoice_number"])
except Exception as e:
print(f"Error: {str(e)}")

Data Validation

# ✅ Validate invoice has required fields
def safe_get_email(invoice):
try:
return invoice["primary_recipients"][0]["billing_info"]["email_address"]
except (KeyError, IndexError):
return "Unknown"

Pagination

# ✅ Handle pagination for large datasets
def get_all_invoices(connection_name="paypal"):
all_invoices = []
page = 1

while True:
result = run_connection_action(
connection_name,
"invoicing/get_v2_invoicing_invoices",
{"page": page, "page_size": 100}
)

items = result["items"]
all_invoices.extend(items)

if len(items) < 100:
break
page += 1

return all_invoices

Troubleshooting

"NOT_AUTHORIZED" Error

  • Cause: Missing API permissions
  • Solution: Enable required features in PayPal Developer Dashboard
    • Go to your app settings
    • Enable: Invoicing, Payments, Subscriptions, Transaction Search

Invalid Invoice ID

  • Cause: Invoice ID format incorrect or invoice doesn't exist
  • Solution: Use the exact ID returned from get_v2_invoicing_invoices
    • Format: INV2-XXXX-XXXX-XXXX-XXXX

Empty Transaction List

  • Cause: Invoice not paid yet or payments not recorded
  • Solution: Check invoice status first
    • Only PAID or PARTIALLY_PAID invoices have transactions

Sandbox vs Production Confusion

  • Cause: Using production credentials in sandbox or vice versa
  • Solution: Verify environment matches credentials
    • Sandbox URLs: api-m.sandbox.paypal.com
    • Production URLs: api-m.paypal.com

Rate Limiting

  • Cause: Too many requests in short time
  • Solution: Implement exponential backoff
    import time

    def retry_with_backoff(func, max_retries=3):
    for i in range(max_retries):
    try:
    return func()
    except Exception as e:
    if i == max_retries - 1:
    raise
    time.sleep(2 ** i)

Resources

Need Help?

  • Check the specific tutorial for detailed examples
  • Review error messages in troubleshooting sections
  • Test with Sandbox environment first
  • Verify credentials and permissions
  • Check PayPal API status page for outages