# Cost+ Payment API

> Cost+ is a REST payment-processing API for European merchants. Create an order, redirect the customer to `payment_url`, confirm via webhook or `GET /orders/{id}`. Cards, Apple Pay, Google Pay, Vipps/MobilePay, SEPA, and more through a single integration.

Docs site: https://docs.costplus.io
Full bundle: https://docs.costplus.io/llms-full.txt
OpenAPI: https://docs.costplus.io/openapi.json

## Base URL

```
https://api.costplus.online/v1
```

There is **no separate sandbox URL**. The API key determines the mode:
- Sandbox website key → simulated transactions (no money moves)
- Production website key → real charges

Manage keys at https://dashboard.costplus.io/ under Websites → *your site* → Integration.

## Authentication

HTTP Basic Auth. Use the **API key as the username** with an **empty password** (the trailing colon is required).

```bash
curl -u YOUR_API_KEY: https://api.costplus.online/v1/orders/
```

Equivalent manual header: `Authorization: Basic <base64("YOUR_API_KEY:")>`. TLS 1.2+ required. Never expose the key in client-side code.

## Money Units

Amounts are **integers in the smallest currency unit** (cents for EUR, öre for SEK, etc.).

- 12.95 EUR → `1295`
- 100 SEK → `10000`
- 1.00 USD → `100`

## First Payment in 4 Steps

### 1. Create an order

```bash
curl -u YOUR_API_KEY: \
  -X POST https://api.costplus.online/v1/orders/ \
  -H 'Content-Type: application/json' \
  -d '{
    "currency": "EUR",
    "amount": 1295,
    "merchant_order_id": "my-first-order",
    "description": "Test order",
    "return_url": "https://example.com/return",
    "failure_url": "https://example.com/cancel",
    "webhook_url": "https://example.com/webhook",
    "transactions": [{ "payment_method": "credit-card" }]
  }'
```

The response contains the order `id` and, inside `transactions[0]`, a `payment_url`:

```json
{
  "id": "4851e31c-4137-4e91-95ef-1df945ee76a2",
  "status": "new",
  "currency": "EUR",
  "amount": 1295,
  "transactions": [
    {
      "id": "d291f03f-...",
      "payment_method": "credit-card",
      "payment_url": "https://pay.costplus.online/4851e31c.../credit-card/d291f03f..."
    }
  ]
}
```

Shortcut: omit `transactions` and use `order_url` from the response — Cost+ then shows the customer all enabled payment methods.

### 2. Redirect the customer

Send the browser to `transactions[0].payment_url` (or `order_url`). The customer completes payment on the Cost+ hosted page.

### 3. Handle the return

The customer returns to:
- `return_url` on success / most statuses
- `failure_url` on `cancelled`, `expired`, or `error`

**Never trust the redirect alone** — the customer may close the browser before the redirect fires, and query params can be tampered with.

### 4. Verify the final status

Use either (preferably both):

**Webhook** — Cost+ POSTs `{"event": "status_changed", "order_id": "..."}` to your `webhook_url`. Always re-fetch the order by ID before acting; return HTTP 200 within a few seconds to acknowledge.

**Polling** — `GET /v1/orders/{id}/?fields[]=amount_details` returns the authoritative status plus capturable / captured / refundable / voidable amounts.

```bash
curl -u YOUR_API_KEY: \
  'https://api.costplus.online/v1/orders/4851e31c.../?fields[]=amount_details'
```

Terminal statuses: `completed`, `cancelled`, `expired`, `error`. Fulfil the order when status is `completed`.

## Core Endpoints

| Method | Path | Purpose |
|---|---|---|
| POST | `/orders/` | Create an order (returns `payment_url`) |
| GET | `/orders/{id}/` | Fetch current status |
| GET | `/orders/` | List orders by date range |
| PUT | `/orders/{id}/` | Update an order (before payment) |
| DELETE | `/orders/{id}/` | Cancel an order |
| POST | `/orders/{id}/refunds/` | Refund by amount or line |
| POST | `/orders/{id}/captures/` | Capture an authorised amount |
| POST | `/orders/{id}/voids/` | Void an authorised amount |
| POST | `/paymentlinks/` | Create a reusable payment link |
| GET | `/paymentlinks/{id}/` | Fetch a payment link + its orders |
| GET | `/search/orders/` | Search orders by merchant_order_id or customer fields |
| GET | `/currencies/` | List supported currencies |

All paths above require Basic Auth. POSTs take `application/json`.

## Test Cards (Sandbox)

| Card | Number | Result |
|---|---|---|
| Visa | `4111 1111 1111 1111` | Success |
| Mastercard | `5544 3300 0000 0037` | Success |
| Visa | `4000 0000 0000 0002` | Do Not Honor |
| Visa | `4000 0000 0000 0069` | Insufficient Funds |

Any future expiry (e.g. `12/28`) and any 3-digit CVC work.

## Webhook Handler Checklist

1. Accept POST with JSON body (e.g. `{"event":"status_changed","order_id":"..."}`).
2. **Re-fetch** the order via `GET /orders/{id}/` — do not trust the payload.
3. Be idempotent — the same event may be delivered more than once.
4. Return HTTP 2xx within a few seconds. Cost+ retries on failure.
5. Fulfil only when `status === "completed"` (or the transaction reaches its terminal paid state).

See https://docs.costplus.io/docs/guides/webhooks for retry schedule and payload schemas.

## Key Links

- Quickstart: https://docs.costplus.io/docs/getting-started/quickstart
- Authentication: https://docs.costplus.io/docs/getting-started/authentication
- Testing & error codes: https://docs.costplus.io/docs/getting-started/testing
- Hosted Payment Page: https://docs.costplus.io/docs/guides/hosted-payment-page
- Payment Links: https://docs.costplus.io/docs/guides/payment-links
- Auth / Capture / Void: https://docs.costplus.io/docs/guides/auth-capture-void
- Refunds: https://docs.costplus.io/docs/guides/refunds
- Webhooks: https://docs.costplus.io/docs/guides/webhooks
- Recurring Payments: https://docs.costplus.io/docs/guides/recurring-payments
- One-Click Payments: https://docs.costplus.io/docs/guides/one-click-payments
- API reference (HTML): https://docs.costplus.io/api-reference/
- OpenAPI spec (JSON): https://docs.costplus.io/openapi.json
- Full Markdown bundle: https://docs.costplus.io/llms-full.txt
- SDKs: Node.js, Python, PHP, Java/Kotlin, C#/.NET, Ruby — https://docs.costplus.io/docs/sdks

## Clean Markdown Per Page

Every docs / API reference page is also available as clean Markdown by appending `.md`:

- https://docs.costplus.io/docs/getting-started/quickstart.md
- https://docs.costplus.io/api-reference/orders/createOrder.md

Use those URLs for LLM ingestion — they contain no HTML, no UI chrome, no nav.
