{"id":326,"date":"2025-08-27T19:54:33","date_gmt":"2025-08-27T19:54:33","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=326"},"modified":"2025-08-27T19:54:36","modified_gmt":"2025-08-27T19:54:36","slug":"how-to-build-a-rest-api-with-laravel-12-sanctum","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/how-to-build-a-rest-api-with-laravel-12-sanctum\/","title":{"rendered":"How to Build a REST API with Laravel 12 &amp; Sanctum"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>How to Build a REST API with Laravel 12 &amp; Sanctum<\/strong><\/h2>\n\n\n\n<p>Building a REST API in Laravel requires a secure way to authenticate requests. <strong>Laravel Sanctum<\/strong> is the recommended package for issuing and managing API tokens. In this guide, you\u2019ll configure Sanctum, protect routes, issue tokens, and build endpoints for authentication and data access. We\u2019ll also build a small test UI to interact with the API.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1 &#8211; Install and Configure Sanctum<\/strong><\/h2>\n\n\n\n<p>First, install Sanctum and publish its configuration and migrations.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">composer require laravel\/sanctum\n\nphp artisan vendor:publish --provider=<span class=\"hljs-string\">\"Laravel\\Sanctum\\SanctumServiceProvider\"<\/span>\n\nphp artisan migrate<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The package creates a <code>personal_access_tokens<\/code> table where issued tokens are stored. Publishing the config file gives you full control over expiration and storage options.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2 &#8211; Enable Sanctum Middleware<\/strong><\/h2>\n\n\n\n<p>Add Sanctum\u2019s middleware to the <code>api<\/code> guard so that token authentication works automatically on protected routes.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Kernel.php (snippet)<\/span>\n<span class=\"hljs-keyword\">protected<\/span> $middlewareGroups = &#91;\n    <span class=\"hljs-string\">'api'<\/span> =&gt; &#91;\n        \\Laravel\\Sanctum\\Http\\Middleware\\EnsureFrontendRequestsAreStateful::class,\n        <span class=\"hljs-string\">'throttle:api'<\/span>,\n        \\Illuminate\\Routing\\Middleware\\SubstituteBindings::class,\n    ],\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Including <code>EnsureFrontendRequestsAreStateful<\/code> allows SPAs and mobile apps to use cookies or tokens seamlessly. Throttling protects APIs against brute force attacks.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3 &#8211; Updating the User Model<\/strong><\/h2>\n\n\n\n<p>Add the <code>HasApiTokens<\/code> trait to the User model so it can issue and manage tokens.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Models\/User.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Foundation<\/span>\\<span class=\"hljs-title\">Auth<\/span>\\<span class=\"hljs-title\">User<\/span> <span class=\"hljs-title\">as<\/span> <span class=\"hljs-title\">Authenticatable<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Laravel<\/span>\\<span class=\"hljs-title\">Sanctum<\/span>\\<span class=\"hljs-title\">HasApiTokens<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">User<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Authenticatable<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">HasApiTokens<\/span>;\n\n    <span class=\"hljs-keyword\">protected<\/span> $fillable = &#91;<span class=\"hljs-string\">'name'<\/span>,<span class=\"hljs-string\">'email'<\/span>,<span class=\"hljs-string\">'password'<\/span>];\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now you can call <code>$user-&gt;createToken()<\/code> to generate tokens tied to the user. Each token can have its own abilities (scopes).<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4 &#8211; Authentication Routes and Controllers<\/strong><\/h2>\n\n\n\n<p>Create endpoints for registering, logging in, and logging out. Tokens are returned after login and should be used in the <code>Authorization<\/code> header.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/api.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">AuthApiController<\/span>;\n\nRoute::post(<span class=\"hljs-string\">'\/register'<\/span>, &#91;AuthApiController::class, <span class=\"hljs-string\">'register'<\/span>]);\nRoute::post(<span class=\"hljs-string\">'\/login'<\/span>, &#91;AuthApiController::class, <span class=\"hljs-string\">'login'<\/span>]);\nRoute::middleware(<span class=\"hljs-string\">'auth:sanctum'<\/span>)-&gt;post(<span class=\"hljs-string\">'\/logout'<\/span>, &#91;AuthApiController::class, <span class=\"hljs-string\">'logout'<\/span>]);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>These routes provide a minimal authentication API. The <code>auth:sanctum<\/code> middleware ensures only valid token holders can call logout.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/AuthApiController.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">User<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Support<\/span>\\<span class=\"hljs-title\">Facades<\/span>\\<span class=\"hljs-title\">Hash<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AuthApiController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">register<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $data = $request-&gt;validate(&#91;\n            <span class=\"hljs-string\">'name'<\/span> =&gt; <span class=\"hljs-string\">'required|string|max:255'<\/span>,\n            <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'required|email|unique:users'<\/span>,\n            <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'required|string|min:6'<\/span>,\n        ]);\n\n        $user = User::create(&#91;\n            <span class=\"hljs-string\">'name'<\/span> =&gt; $data&#91;<span class=\"hljs-string\">'name'<\/span>],\n            <span class=\"hljs-string\">'email'<\/span> =&gt; $data&#91;<span class=\"hljs-string\">'email'<\/span>],\n            <span class=\"hljs-string\">'password'<\/span> =&gt; Hash::make($data&#91;<span class=\"hljs-string\">'password'<\/span>]),\n        ]);\n\n        <span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;<span class=\"hljs-string\">'user'<\/span> =&gt; $user], <span class=\"hljs-number\">201<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">login<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $request-&gt;validate(&#91;\n            <span class=\"hljs-string\">'email'<\/span> =&gt; <span class=\"hljs-string\">'required|email'<\/span>,\n            <span class=\"hljs-string\">'password'<\/span> =&gt; <span class=\"hljs-string\">'required'<\/span>,\n        ]);\n\n        $user = User::where(<span class=\"hljs-string\">'email'<\/span>, $request-&gt;email)-&gt;first();\n\n        <span class=\"hljs-keyword\">if<\/span> (!$user || !Hash::check($request-&gt;password, $user-&gt;password)) {\n            <span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;<span class=\"hljs-string\">'message'<\/span> =&gt; <span class=\"hljs-string\">'Invalid credentials'<\/span>], <span class=\"hljs-number\">401<\/span>);\n        }\n\n        $token = $user-&gt;createToken(<span class=\"hljs-string\">'api-token'<\/span>, &#91;<span class=\"hljs-string\">'*'<\/span>])-&gt;plainTextToken;\n\n        <span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;<span class=\"hljs-string\">'token'<\/span> =&gt; $token]);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">logout<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $request-&gt;user()-&gt;currentAccessToken()-&gt;delete();\n        <span class=\"hljs-keyword\">return<\/span> response()-&gt;json(&#91;<span class=\"hljs-string\">'message'<\/span> =&gt; <span class=\"hljs-string\">'Logged out'<\/span>]);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>login<\/code> method issues a token on success. The token must be sent as <code>Authorization: Bearer &lt;token&gt;<\/code> in subsequent requests. <code>logout()<\/code> revokes the current token by deleting it.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5 &#8211; Protecting API Routes<\/strong><\/h2>\n\n\n\n<p>To secure your API endpoints, wrap them with <code>auth:sanctum<\/code>. Example: protecting a posts resource.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/api.php (snippet)<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>\\<span class=\"hljs-title\">PostApiController<\/span>;\n\nRoute::middleware(<span class=\"hljs-string\">'auth:sanctum'<\/span>)-&gt;group(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    Route::get(<span class=\"hljs-string\">'\/posts'<\/span>, &#91;PostApiController::class, <span class=\"hljs-string\">'index'<\/span>]);\n    Route::post(<span class=\"hljs-string\">'\/posts'<\/span>, &#91;PostApiController::class, <span class=\"hljs-string\">'store'<\/span>]);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now only authenticated users with valid tokens can fetch or create posts. If the token is missing or invalid, Laravel returns a 401 Unauthorized response automatically.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6 &#8211; Example Resource Controller<\/strong><\/h2>\n\n\n\n<p>Here\u2019s a simple API controller for posts. It validates input and ties posts to the authenticated user.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Controllers\/PostApiController.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Controllers<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Models<\/span>\\<span class=\"hljs-title\">Post<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Request<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostApiController<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Controller<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">index<\/span><span class=\"hljs-params\">()<\/span>\n    <\/span>{\n        <span class=\"hljs-keyword\">return<\/span> Post::with(<span class=\"hljs-string\">'user:id,name'<\/span>)-&gt;latest()-&gt;paginate(<span class=\"hljs-number\">10<\/span>);\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">store<\/span><span class=\"hljs-params\">(Request $request)<\/span>\n    <\/span>{\n        $data = $request-&gt;validate(&#91;\n            <span class=\"hljs-string\">'title'<\/span> =&gt; <span class=\"hljs-string\">'required|string|max:255'<\/span>,\n            <span class=\"hljs-string\">'body'<\/span>  =&gt; <span class=\"hljs-string\">'required|string'<\/span>,\n        ]);\n\n        $post = $request-&gt;user()-&gt;posts()-&gt;create($data);\n\n        <span class=\"hljs-keyword\">return<\/span> response()-&gt;json($post, <span class=\"hljs-number\">201<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>index<\/code> endpoint paginates posts and includes the author\u2019s name. The <code>store<\/code> method creates a post linked to the authenticated user, ensuring accountability and traceability.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>7 &#8211; Quick UI: API Tester Blade<\/strong><\/h2>\n\n\n\n<p>For convenience, here\u2019s a small Blade UI to test your API directly in the browser. It uses Axios to make requests with the Bearer token.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!-- resources\/views\/api\/test.blade.php --&gt;\n@extends(<span class=\"hljs-string\">'layouts.app'<\/span>)\n\n@section(<span class=\"hljs-string\">'content'<\/span>)\n&lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">container<\/span>\"&gt;\n  &lt;<span class=\"hljs-title\">h1<\/span>&gt;<span class=\"hljs-title\">API<\/span> <span class=\"hljs-title\">Tester<\/span>&lt;\/<span class=\"hljs-title\">h1<\/span>&gt;\n\n  &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">mb<\/span>-3\"&gt;\n    &lt;<span class=\"hljs-title\">label<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">label<\/span>\"&gt;<span class=\"hljs-title\">Bearer<\/span> <span class=\"hljs-title\">Token<\/span>&lt;\/<span class=\"hljs-title\">label<\/span>&gt;\n    &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">id<\/span>=\"<span class=\"hljs-title\">token<\/span>\" <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">text<\/span>\" <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">form<\/span>-<span class=\"hljs-title\">control<\/span>\" <span class=\"hljs-title\">placeholder<\/span>=\"<span class=\"hljs-title\">Paste<\/span> <span class=\"hljs-title\">your<\/span> <span class=\"hljs-title\">token<\/span> <span class=\"hljs-title\">here<\/span>\"&gt;\n  &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n\n  &lt;<span class=\"hljs-title\">button<\/span> <span class=\"hljs-title\">class<\/span>=\"<span class=\"hljs-title\">btn<\/span> <span class=\"hljs-title\">btn<\/span>-<span class=\"hljs-title\">theme<\/span> <span class=\"hljs-title\">mb<\/span>-3\" <span class=\"hljs-title\">onclick<\/span>=\"<span class=\"hljs-title\">getPosts<\/span>()\"&gt;<span class=\"hljs-title\">Fetch<\/span> <span class=\"hljs-title\">Posts<\/span>&lt;\/<span class=\"hljs-title\">button<\/span>&gt;\n  &lt;<span class=\"hljs-title\">pre<\/span> <span class=\"hljs-title\">id<\/span>=\"<span class=\"hljs-title\">result<\/span>\"&gt;&lt;\/<span class=\"hljs-title\">pre<\/span>&gt;\n&lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n\n&lt;<span class=\"hljs-title\">script<\/span> <span class=\"hljs-title\">src<\/span>=\"<span class=\"hljs-title\">https<\/span>:\/\/<span class=\"hljs-title\">cdn<\/span>.<span class=\"hljs-title\">jsdelivr<\/span>.<span class=\"hljs-title\">net<\/span>\/<span class=\"hljs-title\">npm<\/span>\/<span class=\"hljs-title\">axios<\/span>\/<span class=\"hljs-title\">dist<\/span>\/<span class=\"hljs-title\">axios<\/span>.<span class=\"hljs-title\">min<\/span>.<span class=\"hljs-title\">js<\/span>\"&gt;&lt;\/<span class=\"hljs-title\">script<\/span>&gt;\n&lt;<span class=\"hljs-title\">script<\/span>&gt;\n<span class=\"hljs-title\">function<\/span> <span class=\"hljs-title\">getPosts<\/span>() <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> token = document.getElementById(<span class=\"hljs-string\">'token'<\/span>).value;\n  axios.get(<span class=\"hljs-string\">'\/api\/posts'<\/span>, {\n    headers: { Authorization: `Bearer ${token}` }\n  }).then(res =&gt; {\n    document.getElementById(<span class=\"hljs-string\">'result'<\/span>).textContent =\n      JSON.stringify(res.data, <span class=\"hljs-keyword\">null<\/span>, <span class=\"hljs-number\">2<\/span>);\n  }).<span class=\"hljs-keyword\">catch<\/span>(err =&gt; {\n    document.getElementById(<span class=\"hljs-string\">'result'<\/span>).textContent =\n      err.response ? err.response.status+<span class=\"hljs-string\">' '<\/span>+err.response.statusText : err;\n  });\n}\n&lt;\/script&gt;\n@endsection<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This UI lets you test API endpoints quickly\u2014just paste a token and click \u201cFetch Posts.\u201d Useful for developers or QA before using Postman or mobile clients.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>With Sanctum, building a secure REST API in Laravel is straightforward. You installed and configured Sanctum, updated the User model, built authentication routes, protected endpoints, and added a small UI tester. This approach is lightweight, token-based, and ideal for SPAs and mobile apps. You now have the foundation of a production-ready API.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/using-laravel-with-graphql-a-beginners-guide\">Using Laravel with GraphQL: A Beginner\u2019s Guide<\/a><\/li>\n<li><a href=\"\/blog\/how-to-build-a-multi-auth-api-with-laravel-sanctum\">How to Build a Multi-Auth API with Laravel &amp; Sanctum<\/a><\/li>\n<li><a href=\"\/blog\/how-to-add-jwt-authentication-to-laravel-apis\">How to Add JWT Authentication to Laravel APIs<\/a><\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>How to Build a REST API with Laravel 12 &amp; Sanctum Building a REST API in Laravel requires a secure way to authenticate requests. Laravel Sanctum is the recommended package for issuing and managing API tokens. In this guide, you\u2019ll configure Sanctum, protect routes, issue tokens, and build endpoints for authentication and data access. We\u2019ll [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":330,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[23,25,22],"class_list":["post-326","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-access-control","tag-api","tag-security"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=326"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/326\/revisions"}],"predecessor-version":[{"id":329,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/326\/revisions\/329"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/330"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}