API Documentation
Integrate Go2PAY into your application to create products, send payment requests, and manage your business programmatically.
Contents
https://go2pay.gd/api/v1 — All endpoints are relative to this base.
Authentication
There are two ways to authenticate. Both send a token in the Authorization header, so the rest of this document applies to either.
| Method | Best for | Notes |
|---|---|---|
| API key | Websites, online stores and any server that runs unattended | Does not expire, can be limited to taking payments, and can be revoked on its own. Recommended. |
| Email and password | Apps where a person signs in | Returns a token good for one hour, refreshed with a second token. Unchanged and still fully supported. |
API keys
A key works on every endpoint in this document. It is not only for the WooCommerce plugin: anything you can do by signing in with your email and password, you can do with a key set to Everything my account can do — without a password stored in your code, and with the ability to switch that one key off without changing anything else.
Create one while signed in at https://go2pay.gd/integration-keys, under API Keys. The key is shown once, when you create it. We store only a scrambled copy, so if you lose it you revoke it and make another.
Send it exactly like a token:
curl https://go2pay.gd/api/v1/orders \
-H "Authorization: Bearer g2p_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Each key is created with one of two permissions:
| Permission | What it may call |
|---|---|
Take payments only |
POST /requests, GET /requests, GET /requests/{id},
GET /orders, GET /orders/{id}, GET /auth/me.
Everything else is refused with 403, including refunds and anything to do with withdrawals or bank accounts.
|
Everything my account can do |
Every endpoint in this document, the same as signing in with a password. |
Live keys and test keys
Keys come in two kinds, and the kind is carried in the key itself, so there is no setting to get wrong.
| Prefix | What it does |
|---|---|
g2p_live_ |
Real payments against real cards. Money reaches the vendor's balance. |
g2p_test_ |
Runs the whole flow with no money. Only test card numbers are accepted, and the resulting orders never appear in balances, sales totals, withdrawals or stock counts. |
Everything else behaves identically, so the same integration code works for both: swap the key and nothing else. Test payments are clearly marked on the payment page so nobody mistakes one for a real sale.
Use these card numbers with a test key, with any future expiry date and any security code. A real card is refused on a test key.
| Card number | Result |
|---|---|
4242 4242 4242 4242 | Succeeds |
4000 0000 0000 0002 | Declined |
4000 0000 0000 9995 | Declined, insufficient funds |
4000 0025 0000 3155 | Requires extra authentication |
5555 5555 5555 4444 | Succeeds (Mastercard) |
A real card is refused on a test key. A live key takes real cards as normal.
Email and password
Login with your email and password to receive an access token. This is what the mobile app uses, and nothing about it has changed.
POST /auth/login
Authenticate and receive tokens.
curl -X POST https://go2pay.gd/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "your_password"}'
Response:
{
"success": true,
"data": {
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"expires_in": 3600,
"user": { "id": 123, "first_name": "John", "email": "you@example.com" }
}
}
POST /auth/refresh
Refresh an expired access token using your refresh token (valid for 30 days).
curl -X POST https://go2pay.gd/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "eyJ..."}'
Authorization header on all protected requests:
Authorization: Bearer eyJ...
An API key goes in the very same header, and never needs refreshing:
Authorization: Bearer g2p_live_...
Products
Create and manage payment links for your products or services.
POST /products
Create a new product and receive a payment link.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Product name |
price | decimal | Yes | Price in USD |
description | string | No | Product description |
max_quantity | int | No | Max qty per order (default: 10) |
quantity_available | int | No | Stock available (null = unlimited) |
endpoint | url | No | Webhook URL — receives POST on payment |
success_url | url | No | Redirect after successful payment |
error_url | url | No | Redirect on error |
purchase_note | string | No | Note shown on receipt |
curl -X POST https://go2pay.gd/api/v1/products \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Premium Plan",
"price": 49.99,
"description": "Monthly subscription",
"endpoint": "https://mysite.com/webhook"
}'
Response includes payment_url — share this link with customers:
{
"success": true,
"data": {
"id": 123,
"title": "Premium Plan",
"price": 49.99,
"payment_url": "https://go2pay.gd/123",
...
}
}
GET /products
List your products. Supports ?page=1&q=search&type=product
GET /products/{id}
Get a single product with order stats and payment URL.
PUT /products/{id}
Update a product. Send only the fields you want to change.
DELETE /products/{id}
Archive (soft-delete) a product.
Payment Requests
Send a one-time payment request to a specific customer. Creates a payment link and optionally emails it.
POST /requests
Create a payment request.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Customer name |
email | string | Yes | Customer email |
amount | decimal | Yes | Amount in USD |
phone | string | No | Customer phone |
description | string | No | Note shown to customer |
endpoint | url | No | Webhook URL (HTTPS only) |
success_url | url | No | Redirect after payment |
error_url | url | No | Redirect on error |
send_email | bool | No | Email the payment link to the customer (default true) |
send_receipt | bool | No | Email the customer a receipt after they pay (default true; the vendor's copy always sends) |
curl -X POST https://go2pay.gd/api/v1/requests \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"amount": 150.00,
"description": "Invoice #1234",
"send_email": true,
"send_receipt": false
}'
{
"success": true,
"data": {
"id": 456,
"payment_url": "https://go2pay.gd/456",
"title": "John Doe",
"price": 150.00,
"email": "john@example.com",
"email_sent": true
}
}
send_email: false skips the payment-link email to the customer
(email_sent will be false).
send_receipt: false skips the customer's receipt email after they pay
— use both when your site sends its own emails. The vendor's receipt copy and
your webhook endpoint always fire regardless.
GET /requests
List your payment requests. Supports ?page=1&q=search
GET /requests/{id}
Get a single payment request with order stats.
DELETE /requests/{id}
Archive a payment request.
Subscriptions
Create recurring plans and manage their subscribers. A plan charges the customer's saved card automatically each billing period. Subscription charges appear in your Orders and are withdrawable like any other sale.
POST /subscriptions
Create a subscription plan. Returns a subscribe_url to share with customers.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Plan name (e.g. "Gold Membership") |
price | decimal | Yes | Recurring price in USD |
billing_interval | string | Yes | One of weekly, monthly, quarterly, yearly |
description | string | No | Shown on the sign-up page |
trial_days | int | No | Free trial length in days (default 0) |
setup_fee | decimal | No | One-time fee charged on the first cycle (default 0) |
max_charges | int | No | Auto-cancel after this many charges (null = unlimited) |
pay_processing_fee | bool | No | Absorb the processing fee instead of passing it to the subscriber |
show_address | bool | No | Collect a billing address at checkout |
cancel_on_dispute | bool | No | Auto-cancel the subscription if a charge is disputed (default true) |
success_url / cancel_url | url | No | Redirects after checkout |
curl -X POST https://go2pay.gd/api/v1/subscriptions \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json" \
-d '{
"name": "Gold Membership",
"price": 9.99,
"billing_interval": "monthly",
"trial_days": 7,
"setup_fee": 5.00
}'
Response includes subscribe_url — share this link (or its QR / embed card) with customers:
{
"success": true,
"message": "Subscription created successfully",
"data": {
"id": 42,
"name": "Gold Membership",
"price": 9.99,
"billing_interval": "monthly",
"trial_days": 7,
"cancel_on_dispute": true,
"subscribe_url": "https://go2pay.gd/subscribe/2b3c…"
}
}
GET /subscriptions
List your plans (paginated) with subscriber and revenue counts. Supports
?page=1&limit=20&q=search&include_archived=false.
GET /subscriptions/{id}
Get a plan with its list of subscribers.
PUT /subscriptions/{id}
Update a plan. Price/interval changes apply to future cycles only. Accepts the same fields as create.
DELETE /subscriptions/{id}
Archive a plan. It stops accepting new sign-ups; existing subscribers keep billing until cancelled.
GET /subscriptions/{id}/subscribers
List a plan's subscribers (status, card, next charge date, cycles).
POST /subscriptions/subscribers/{signupId}/cancel
Cancel a subscriber — they will not be charged again.
POST /subscriptions/subscribers/{signupId}/pause
Pause a subscriber's billing (excluded from charging while paused).
POST /subscriptions/subscribers/{signupId}/resume
Resume a paused subscriber. The next charge date shifts forward by the paused duration.
Orders
View and manage orders placed through your payment links.
GET /orders
List orders. Supports ?page=1&status=PAID&q=search&product_id=123
GET /orders/{id}
Get a single order with full details.
POST /orders/{id}/refund
Refund an order through Stripe. Supports full and partial refunds; partial refunds may be repeated up to the order total.
| Field | Type | Required | Description |
|---|---|---|---|
amount | decimal | No | Amount to refund in USD. Omit to refund the full remaining balance. Capped at the remaining balance if larger. |
reason | string | No | Refund reason. duplicate, fraudulent, or requested_by_customer are passed to Stripe; any other text is stored as a note. |
Send an optional Idempotency-Key header to make retries safe — repeating a request with the same key will not refund twice.
curl -X POST https://go2pay.gd/api/v1/orders/789/refund \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: refund-789-001" \
-d '{"amount": 25.00, "reason": "requested_by_customer"}'
Response:
{
"success": true,
"message": "Refund processed successfully",
"data": {
"order_id": 789,
"refunded_amount": 25.00,
"total_refunded": 25.00,
"status": "PARTIAL REFUND",
"stripe_refund_id": "re_3Ab1Cd..."
}
}
status is PARTIAL REFUND while a balance remains, or REFUNDED once fully refunded.
| Code | Meaning |
|---|---|
404 | Order not found or not owned by your account |
409 | Order has an active dispute, or has already been withdrawn |
400 | No payment to refund, already fully refunded, or outside the refund window |
422 | Refund amount is not greater than zero |
429 | Too many requests to Stripe — retry shortly |
Customers
Customers are created automatically when payments are made. You can list and view them.
GET /customers
List customers with order stats. Supports ?q=search
GET /customers/{id}
Get customer detail with last 10 orders.
Webhooks & Callbacks
When a customer completes a payment, Go2PAY sends a POST request to the endpoint URL you specified when creating the product or request.
Callback Payload
The following JSON is POSTed to your endpoint after a successful payment:
{
"order_id": 789,
"api_order_id": "your-external-id",
"product_id": 123,
"status": "PAID",
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "473-123-4567",
"price": 49.99,
"qty": 1,
"subtotal": 49.99,
"customer_total": 52.44,
"currency": "USD",
"payment_id": "pi_xxx",
"created": "2026-04-06T18:00:00+00:00"
}
Response Format
All responses follow this structure:
// Success
{
"success": true,
"message": "Description",
"data": { ... }
}
// Paginated
{
"success": true,
"data": [ ... ],
"pagination": {
"page": 1,
"limit": 20,
"total": 85,
"total_pages": 5
}
}
// Error
{
"success": false,
"message": "Error description"
}
Error Codes
| Code | Meaning |
|---|---|
400 | Bad Request — invalid data or business rule violation |
401 | Unauthorized — missing or invalid token, or an API key that is unknown or revoked |
403 | Forbidden — not a vendor, account inactive, or an API key limited to taking payments was used on another endpoint |
404 | Not Found — resource doesn't exist or isn't yours |
422 | Validation Error — missing required fields |
500 | Server Error — contact support |
Quick Start (JavaScript)
Example 1: Create a Payment Product
// 1. Login
const auth = await fetch('https://go2pay.gd/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'you@example.com', password: 'pass' })
}).then(r => r.json());
const token = auth.data.access_token;
// 2. Create a product
const product = await fetch('https://go2pay.gd/api/v1/products', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({
title: 'Premium Plan',
price: 49.99,
description: 'Monthly subscription',
max_quantity: 1,
endpoint: 'https://mysite.com/webhook',
success_url: 'https://mysite.com/thank-you'
})
}).then(r => r.json());
// 3. Share the payment link with your customers
console.log(product.data.payment_url);
// → https://go2pay.gd/123
Example 2: Send a Payment Request
// Using the same token from above...
// Create a payment request and email it to the customer
const request = await fetch('https://go2pay.gd/api/v1/requests', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({
name: 'John Doe',
email: 'john@example.com',
amount: 150.00,
description: 'Invoice #1234',
endpoint: 'https://mysite.com/webhook',
send_email: false, // your site emails the payment link itself
send_receipt: false // your site emails its own receipt after payment
})
}).then(r => r.json());
console.log(request.data.payment_url);
// → https://go2pay.gd/456
console.log(request.data.email_sent);
// → true