Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

chrisan's avatar

Possible to have custom 404 for API?

Using Route::domain('api.example.com') for API routes, how could one setup something where you get a different 404 for all API requests

https://api.github.com/emojis and https://api.github.com/emogees

vs

https://github.com/featuers and https://github.com/features

0 likes
7 replies
itsfg's avatar

What could be a custom 404 for an API ? Adding a custom message ? 404 code should be enough.

This is exactly what you see on the page https://api.github.com/emogees

This is your browser formatting a bit the json response you get from Github API.

Laravel already have this behaviour implemented :

  • 404 on an API page : json response with 404 HTTP code
  • 404 on a website page : custom blade view stored in resources/views/errors/404.blade.php
chrisan's avatar

404 on an API page : json response with 404 HTTP code

Hmm, then perhaps I have something else wrong as the API routes return a HTML 404 response instead of a JSON one

chrisan's avatar

OK, no not anything else unless I'm miss understanding something

composer create-project laravel/laravel example-app

Then edit api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('api')->get('/foo', function(Request $request) {
    return [];
});

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

visit http://localhost:8000/api/foo and we see a json empty array

however visit http://localhost:8000/api/bar and we get a HTML 404

And to be clear, I'm specifically looking for this formatting on 404s of bogus/not defined routes

chrisan's avatar
chrisan
OP
Best Answer
Level 2

Looks like you need to handle it in Handler.php

  /**
   * Render an exception into an HTTP response.
   *
   * @param \Illuminate\Http\Request $request
   * @param \Exception $exception
   * @return \Symfony\Component\HttpFoundation\Response
   *
   * @throws \Exception
   */
  public function render($request, Exception $exception) {
    if (strpos($request->getRequestUri(), '/api/', 0) === 0 &&
      get_class($exception) === NotFoundHttpException::class) {
        return response()->json(['message' => 'Not found'], 404);
    }

    return parent::render($request, $exception);
  }
martinbean's avatar

Hmm, then perhaps I have something else wrong as the API routes return a HTML 404 response instead of a JSON one

@chrisan They will if you’re hitting your routes in the browser and not sending an Accept: application/json header.

stderr33's avatar

You could write it like this:


public function render($request, Throwable $exception)
{
    if ($exception instanceof ModelNotFoundException && $request->isJson()) {
        return response()->json(['message' => 'Record not found'], 404);
    }

    return parent::render($request, $exception);
}

tetranyble's avatar

@stderr33 I have tested this and does not work. Here is what worked for me according to the documentation. https://laravel.com/docs/9.x/errors#rendering-exceptions

/**
 * Register the exception handling callbacks for the application.
 *
 * @return void
 */
public function register()
{
    $this->renderable(function (NotFoundHttpException $e, $request) {
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'Record not found.'
            ], 404);
        }
    });
}

Please or to participate in this conversation.