Calling the OtpGet Email API from Laravel: A Clean Service Class
Calling an HTTP API from a controller works until the second endpoint arrives. A small service class keeps the key in config, the timeouts in one place and the polling logic testable. This guide shows the shape of it for the OtpGet email endpoint. Check the parameter list on the API page before you copy anything.
What the endpoint looks like
The email handler lives at https://otpget.com/stubs/email-handler.php and takes an api_key, an action and the order details. The actions used in this flow are buy, get, cancel and reorder. The returned status is a string, so compare it as a string.
Step 1: config
- Add the key to your
.envfile and never commit it. - Expose it in
config/services.phpunder anotpgetkey. - Read it with
config('services.otpget.key'), not withenv()in application code, so it still works when config is cached.
Step 2: the service class
class OtpGetEmail {
public function call(array $params): array {
$r = Http::timeout(20)->retry(2, 500)
->get('https://otpget.com/stubs/email-handler.php',
$params + ['api_key' => config('services.otpget.key')]);
$r->throw();
return $r->json() ?? [];
}
}Step 3: polling without hammering
- Poll about every 30 to 35 seconds, not every second.
- Stop after the time limit and cancel the order so that it can be refunded.
- Run the polling in a queued job, not in the web request.
Step 4: errors worth handling
- Network timeout: retry a small number of times, then surface a clear message.
- Non-success status: show the text from the response, not a raw exception.
- Low wallet balance: show a top-up message instead of a failure.
Step 5: tests
Fake the call with Http::fake() and assert on the three paths: code received, no code before the limit and cancel. Your tests should never touch the real endpoint or spend wallet money.
Putting the polling in a job
class PollEmailCode implements ShouldQueue {
public function handle(OtpGetEmail $api) {
$res = $api->call(['action'=>'get','id'=>$this->orderId]);
// read the status as a string, then release or finish
}
}Checklist before production
- Timeouts and retry limits are set.
- The key is read from config.
- Polling stops after the time limit and the order is cancelled.
- Errors reach your log without the key in them.
- Tests use Http::fake().
Questions people ask
Should the API key be in the database?
Keep it in environment config. Put it in the database only if you rotate it per tenant, and then encrypt it.
Does currency affect billing?
The currency parameter is for display. The wallet is charged in PKR.
Related guides and pages
Create a free OtpGet account and try it with a small balance.