Skip to content
Engineering

An SMM API request timed out. Should you place the order again?

Recover an SMM API timeout with the same request_id. Learn NotPanel’s 60-second duplicate guard, key conflicts, and order_details lookups.

An order card with a retry arrow and protective shield.

Sameer

Researcher

Retry the same logical order with its original request_id and unchanged order details. Do not create a fresh request ID just because the response timed out. On NotPanel, the retry returns the original order with replayed: true, or places it if the first attempt never arrived.

This matters at checkout. Your customer has submitted one purchase, your application has sent it to the panel, and the response disappears. The next action should recover that purchase without turning the missing response into permission to buy again.

A timeout leaves three possible outcomes

  • The request never arrived, so no order was accepted.
  • The order was accepted, but its response never reached your application.
  • The request arrived while the connection failed; a retry with the same request_id settles which of the first two happened.

A client timeout cannot distinguish these cases. HTTP does not make an order-creating POST safe to repeat by itself; the API’s retry contract supplies that protection. See RFC 9110, §9.2.2.

The two ways NotPanel recognises a retry

For caller-controlled retries, send request_id once per logical order. It is optional, must be nonempty, and can contain up to 128 characters. idempotency_key is its compatibility alias; request_id wins if both are supplied. Reuse the same key on the same account with the same order parameters. Once the order is accepted, its replay returns the original order ID. Reusing that key with different parameters is rejected.

Older clients can omit both fields. NotPanel then protects identical add payloads from the same account for 60 seconds. A repeat inside that window returns the first order instead of a second one. This is useful compatibility protection, but a later retry should not depend on that short window.

The same rule also affects intentional duplicates: two identical legacy adds inside the 60-second window resolve to the same request. Give each genuinely new purchase its own request_id when you want two separate orders immediately. Never change the key merely to escape an uncertain result.

Read the place-order parameters and response contract

  1. Keep the original request_id after a timeout.

  2. Retry with the same key and unchanged order details.

  3. Save the original order ID that the retry returns.

Illustrative recovery flow. A replay returns the accepted order and its original charge.

Give the purchase an identity before sending it

Suppose checkout 8427 contains one order line. Save its request_id and complete order parameters before the first network attempt. This schematic request uses placeholders and line breaks for readability; encode the actual form body normally. Submit actual values only when you intend to place a paid order.

POST https://notpanel.com/api/v3
Content-Type: application/x-www-form-urlencoded

key=YOUR_API_KEY
&action=add
&service=YOUR_SERVICE_ID
&link=YOUR_TARGET_URL
&quantity=YOUR_VALID_QUANTITY
&request_id=checkout-8427-line-1

If that call times out, resend checkout-8427-line-1 with the same service, target, quantity, and any optional fields. Do this even after your application restarts. When a response supplies an order ID, save it against that checkout line and use status to track delivery. request_id identifies the placement attempt; it is not an order ID for a status lookup. Use order_details to look an order up by request_id.

Decide from the response, not just the HTTP number

Timeout, lost connection, or uncertain server response
Keep the original key and payload. Retry with a bounded delay, honour Retry-After when present, and retain an unresolved record if your retry budget runs out.
INTERNAL_ERROR, API_DISABLED or ORDER_PLACEMENT_PAUSED (retryable: true)
Wait, honouring Retry-After when present, then send the same add with the same request_id. You get the original order or a single new one. Do not submit a replacement under another key.
REQUEST_ID_CONFLICT
Compare the saved payload with what you just sent. Restore the original details to recover the original order; use a new key only for a deliberately separate purchase.
Validation, authentication, or rate-limit error
Read error_code and retryable. Fix invalid fields or credentials; respect rate-limit delays. A blanket rule that retries every error can repeat an error indefinitely.

Test the recovery path before accepting customer orders

Start with a mock API in your own test environment. These checks do not require a live purchase or a special NotPanel test key.

  1. Simulate an accepted order followed by a lost response. Confirm the retry uses exactly the saved key and payload.
  2. Restart the client between attempts. Confirm it recovers the same request identity from persistent storage.
  3. Return a retryable 500 or 503, then a replay with replayed: true. Confirm the client saves one order ID.
  4. Return a key conflict or a non-retryable validation error. Confirm automatic attempts stop for investigation.
  5. Create two intentional purchases with identical details. Confirm they receive different request IDs. For any later live test, use an order you actually want and verify the order and wallet records.

Frequently asked questions

Does a timeout mean I was charged twice?

No. It means your application did not receive a usable response. Check the recovered order and wallet records before concluding that a duplicate debit happened.

Is request_id required on NotPanel?

No. request_id and its idempotency_key alias are optional. Without them, identical adds from the same account have 60-second protection. Explicit keys give your application control over each logical order’s identity.

Should I generate a new request_id for every retry?

No. Generate and save one key before the first attempt, then reuse it with unchanged order parameters. A new purchase gets a new key; a network retry keeps the old one.

Can I look an order up with request_id?

Yes, with order_details: send action=order_details with the same request_id to get the order and its number without replaying the add. It returns ORDER_NOT_FOUND when no order was placed. The status action itself still takes the order number.

Continue with: the full API integration guide · webhooks and status polling · the error reference.

Share this post