Skip to content

Quickstart

This guide takes you from zero to a working test payment. It takes about ten minutes.

1. Get your sandbox keys

Sign in at app.ourapayment.com with Google. You get test keys straight away:

Key Looks like Where it lives
Secret key sk_test_… Your server only. Never ship it to a browser or app.
Webhook secret Shown in the dashboard Your server only. Used to verify webhook signatures.

Store both as environment variables:

export OURA_SECRET_KEY=sk_test_...
export OURA_WEBHOOK_SECRET=...

2. Install an SDK

npm install @oura/sdk
pip install oura
composer require oura/oura
go get github.com/oura-pay/oura-go
<dependency>
  <groupId>money.oura</groupId>
  <artifactId>oura-java</artifactId>
  <version>0.1.0</version>
</dependency>
dotnet add package Oura
gem install oura

No SDK for your stack? Every SDK is a thin wrapper over the REST API.

3. Create a payment

Amounts are integers in paisa: 245000 is NPR 2,450.00.

import { Oura } from '@oura/sdk';

const oura = new Oura(process.env.OURA_SECRET_KEY!);

const payment = await oura.payments.create({
  amount: 245000,
  methods: ['esewa', 'khalti'],
  reference: 'order_1042',
  return_url: 'https://himalstore.com.np/orders/1042',
});

res.redirect(payment.checkout_url);
import os
from oura import Oura

oura = Oura(os.environ["OURA_SECRET_KEY"])

payment = oura.payments.create({
    "amount": 245000,
    "methods": ["esewa", "khalti"],
    "reference": "order_1042",
    "return_url": "https://himalstore.com.np/orders/1042",
})

return redirect(payment["checkout_url"])
use Oura\Client;

$oura = new Client(getenv('OURA_SECRET_KEY'));

$payment = $oura->payments->create([
    'amount'     => 245000,
    'methods'    => ['esewa', 'khalti'],
    'reference'  => 'order_1042',
    'return_url' => 'https://himalstore.com.np/orders/1042',
]);

header('Location: ' . $payment['checkout_url']);
client, err := oura.NewClient(os.Getenv("OURA_SECRET_KEY"))
if err != nil {
    log.Fatal(err)
}

payment, err := client.Payments.Create(oura.CreateParams{
    Amount:    245000,
    Methods:   []string{"esewa", "khalti"},
    ReturnURL: "https://himalstore.com.np/orders/1042",
}, "")
if err != nil {
    log.Fatal(err)
}

http.Redirect(w, r, payment["checkout_url"].(string), http.StatusSeeOther)
OuraClient oura = new OuraClient(System.getenv("OURA_SECRET_KEY"));

Map<String, Object> params = Payments.params();
params.put("amount", 245000);
params.put("methods", List.of("esewa", "khalti"));
params.put("return_url", "https://himalstore.com.np/orders/1042");

Map<String, Object> payment = oura.payments.create(params);
String checkoutUrl = (String) payment.get("checkout_url");
var oura = new OuraClient(Environment.GetEnvironmentVariable("OURA_SECRET_KEY")!);

var payment = await oura.Payments.CreateAsync(new Dictionary<string, object?>
{
    ["amount"] = 245000,
    ["methods"] = new[] { "esewa", "khalti" },
    ["return_url"] = "https://himalstore.com.np/orders/1042",
});

return Results.Redirect(payment.GetProperty("checkout_url").GetString()!);
oura = Oura::Client.new(ENV.fetch('OURA_SECRET_KEY'))

payment = oura.payments.create(
  amount: 245000,
  methods: %w[esewa khalti],
  return_url: 'https://himalstore.com.np/orders/1042'
)

redirect_to payment['checkout_url'], allow_other_host: true
curl https://api.ourapayment.com/v1/payments \
  -H "Authorization: Bearer $OURA_SECRET_KEY" \
  -H "Idempotency-Key: order_1042" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 245000,
    "methods": ["esewa", "khalti"],
    "reference": "order_1042",
    "return_url": "https://himalstore.com.np/orders/1042"
  }'

4. Handle the webhook

The customer coming back to return_url is not proof of payment. Fulfil the order only when a verified payment.succeeded webhook arrives. See Webhooks for every language.

import { webhooks } from '@oura/sdk';

app.post('/webhooks/oura', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = webhooks.constructEvent(
      req.body.toString('utf8'),
      req.header('X-Oura-Signature')!,
      process.env.OURA_WEBHOOK_SECRET!,
    );
    if (event.type === 'payment.succeeded') {
      // Mark the order paid. Make this idempotent: webhooks can arrive more than once.
    }
    res.sendStatus(200);
  } catch {
    res.sendStatus(400);
  }
});

5. Test it

Open the checkout_url, pick a method and complete the sandbox payment. Your webhook endpoint should receive payment.succeeded. Then read Go live.