Quickstart
Quickstart
Take one payment from start to finish: create a deposit, send your customer to the payment page, receive the webhook and check the deposit.
This page is the short version. The integration guide goes from your first test key to going live, step by step, with a complete example in curl, PHP, Node.js and Python for each step: the commands below run its curl files, saved under their own names. Prefer to click first? Use the Postman collection.
1. Get your secret key#
Get your secret key from the merchant panel and keep it on your server. Send it on every request as
Authorization: Bearer <key>. A test key (sk_test_…) makes and sees only test
deposits, which never move real money; a live key works once we turn live mode on for your account (until then it
answers live_mode_disabled). Build and test with a test key. You can limit a key to your own
servers: IP allowlist.
The examples read the API's address, your test key, your webhook URL and your test webhook secret from the environment. Run these lines once, with your own values:
export API_URL=https://api.no1paytest.com
export API_KEY=sk_test_…
export WEBHOOK_URL=https://shop.example/webhooks/payments
export WEBHOOK_SECRET=whsec_…
2. Create a deposit#
POST https://api.no1paytest.com/v1/deposits with an Idempotency-Key (for example your order id): the
same key and body again return the same deposit, so a retry after a timeout is safe. Amounts are whole numbers,
IRR in rials. Every deposit and withdrawal needs a webhook_url (any public https address on
your server, up to 2,048 characters): it is the only place its webhooks go.
Save the guide's create-deposit.sh (or its PHP, Node.js or Python version) and run it:
bash create-deposit.sh order-10542 1500000 account_transfer
The answer is 201 with the deposit: keep its id (dep_…) with your order, and
put it in DEPOSIT_ID for the commands below. Every field: guide, step 2.
The command sends a method, so the customer goes straight to that method's payment page. Leave
method out (no third argument) and the customer picks on our method selection page instead:
guide, step 3.
export DEPOSIT_ID=dep_…
3. Send your customer to the payment page#
Redirect the customer's browser to payment_url from the answer: use it exactly as it comes. Afterwards the customer comes back to
your redirect_url. Coming back is never proof of payment: wait for the webhook or check the deposit.
4. Receive the webhook#
When the deposit changes we POST a signed JSON event (deposit.paid, with the deposit in
data) to the deposit's own webhook_url, the address you sent when you created it. Webhooks follow
Standard Webhooks: check Webhook-Id,
Webhook-Timestamp and Webhook-Signature with
your webhook secret (whsec_…) before you trust one: how, with an
example in each language. Answer 2xx quickly, de-duplicate by Webhook-Id,
ignore an event whose data.version is lower than one you already processed, and check
mode: test webhooks are signed with your test webhook secret, live ones with your live secret, so
verify each with the secret of its mode. We send each event once; the same one can still arrive again (a "Send again", a lost
answer), which is why you de-duplicate. To have us try again over about 2 days when a try fails, turn on
Automatic retries on the Developers page: they are off by default.
5. Confirm with GET#
Save the guide's get-deposit.sh (or its PHP, Node.js or Python version) and run it:
bash get-deposit.sh "$DEPOSIT_ID"
Check status is paid before you deliver the order: every status.
Test mode#
A deposit made with a test key is a test deposit ("mode": "test"): its payment page says "Test payment"
and has three buttons (paid, failed, expired) instead of a real payment; for a bank account transfer it also shows a
made-up account. A test deposit never reaches a bank gateway. End one from your server with a test key
(guide). Save the guide's simulate-deposit.sh (or its PHP, Node.js or Python version) and run it:
bash simulate-deposit.sh "$DEPOSIT_ID" paid
Test data#
A test key takes only made-up numbers with a fixed outcome: test cards for card-to-card deposits, fixed test codes, test Shebas for withdrawals and test tracking numbers for bank transfers. Any real card or Sheba is refused in test mode, and the test ones are refused in live mode. Every number and what it does: guide, step 8, Test data.
Withdrawals#
POST https://api.no1paytest.com/v1/withdrawals pays your customer out to their own card and Sheba:
guide, step 12.
Errors#
Errors are application/problem+json with a readable code and a request_id
(send it to us when you need help): guide, step 10. Every code:
bad_request(400) Bad requestvalidation_failed(422) The request is not validauthentication_failed(401) Authentication failedpermission_denied(403) Permission deniednot_found(404) Not foundmethod_not_allowed(405) Method not allowedidempotency_key_reused(409) Idempotency key was already used with a different requestmethod_unavailable(422) This payment method is not available right nowdeposit_not_found(404) Deposit not foundpayload_too_large(413) Request body is too largerate_limit_exceeded(429) Too many requestsinternal_error(500) Internal errorservice_unavailable(503) Service temporarily unavailabledevice_disabled(403) This phone is disabled in the paneldeposit_expired(a failure_code, never an HTTP answer) The deposit expired before it was paidlive_mode_disabled(403) Live mode is not turned on for this merchanttest_mode_only(403) This works only in test modedeposit_not_open(409) The deposit is not open any morepayment_failed(a failure_code, never an HTTP answer) The payment did not go throughunknown_user_level(422) There is no user level with this nameamount_outside_level_limits(422) The amount is outside the limits of the customer's user levelcustomer_blocked(403) This customer is blockedcustomer_method_blocked(403) This customer is blocked from this payment methodgateway_unavailable(a failure_code, never an HTTP answer) No bank gateway could take this paymentip_not_allowed(403) This key may not be used from this IP addressamount_outside_method_limits(422) The amount is outside your limits for this methodwithdrawal_not_found(404) Withdrawal not foundwithdrawal_not_open(409) The withdrawal is not opencard_transfer_failed(a failure_code, never an HTTP answer) The card transfer could not be madedeposit_cancelled(a failure_code, never an HTTP answer) The customer cancelled the paymentcustomer_has_recent_withdrawal(409) This customer has a recent withdrawal