PHPackages                             laraveldaily/api-starter-kit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. laraveldaily/api-starter-kit

ActiveProject[API Development](/categories/api)

laraveldaily/api-starter-kit
============================

A Laravel API-only starter kit with Sanctum token authentication, account management, and OpenAPI docs.

v1.0.3(1mo ago)3370↓50%8MITPHPPHP ^8.3CI passing

Since Jun 12Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/LaravelDaily/api-starter-kit)[ Packagist](https://packagist.org/packages/laraveldaily/api-starter-kit)[ RSS](/packages/laraveldaily-api-starter-kit/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (13)Versions (5)Used By (0)

Laravel API Starter Kit
=======================

[](#laravel-api-starter-kit)

A Laravel **API-only** starter kit: token-based authentication and account management as plain, readable Laravel code. No front-end, no Vite, no Fortify — just controllers, Form Requests, API Resources, and a green test suite.

**Disclaimer**: this starter kit was built fully by Claude Fable 5 model, after deep planning session and a few building iterations. So it wasn't a one-shot or vibe-coding, but LLM did all the implementation work.

Features
--------

[](#features)

- **Token auth** via [Laravel Sanctum](https://laravel.com/docs/sanctum) personal access tokens — DB-backed, revocable, works for mobile, SPA, and CLI clients.
- **Code-based password reset** — the API emails a 6-digit code, the client posts it back. No reset links, no `FRONTEND_URL`, no assumption about your front end.
- **OpenAPI docs** via [Scramble](https://scramble.dedoc.co) at `/docs/api`.
- **Fully tested** — a Pest feature test for every endpoint; `php artisan test`is green immediately after install.

Installation
------------

[](#installation)

```
laravel new my-app --using=laraveldaily/api-starter-kit
```

The installer asks two questions:

- **Which testing framework do you prefer?** Pick **Pest** — the kit's test suite is already written with it.
- **Would you like to run npm install and npm run build?** Answer **No** — this kit ships no front-end, so there is nothing to install or build. (The installer asks this for every starter kit; it cannot be skipped from the kit's side on current installer releases.)

Or with Composer directly (no prompts at all):

```
composer create-project laraveldaily/api-starter-kit my-app
```

Either way you get a generated `APP_KEY`, an SQLite database, and migrated tables out of the box. Start the server with:

```
php artisan serve
```

The mailer defaults to `MAIL_MAILER=log`, so password reset codes land in `storage/logs/laravel.log` — the whole auth flow works with zero mail setup.

Endpoints
---------

[](#endpoints)

All routes live under `/api/v1`. Authenticated routes expect an `Authorization: Bearer ` header. All responses (including errors) are JSON.

MethodPathAuthPurposePOST`/api/v1/register`–Create an account, receive a tokenPOST`/api/v1/login`–Issue a token for valid credentialsPOST`/api/v1/forgot-password`–Email a 6-digit reset codePOST`/api/v1/reset-password`–Set a new password using the codePOST`/api/v1/logout`✓Revoke the current tokenGET`/api/v1/user`✓Get the authenticated userPUT`/api/v1/user`✓Update name and/or emailPUT`/api/v1/user/password`✓Change password (revokes other tokens)DELETE`/api/v1/user`✓Delete the account (password confirmed)GET`/api/v1/tokens`✓List active tokensDELETE`/api/v1/tokens/{id}`✓Revoke one tokenDELETE`/api/v1/tokens`✓Revoke all tokens except the current one### Register

[](#register)

`device_name` is optional everywhere a token is issued; it defaults to `api`.

```
curl -X POST http://localhost:8000/api/v1/register \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{
    "name": "Jane Doe",
    "email": "jane@example.com",
    "password": "secret-password",
    "password_confirmation": "secret-password",
    "device_name": "iphone-15"
  }'
```

```
{
  "token": "1|x6tLxhBuYDQwGesgZQGMqLpdo1Wt8h9dLn1to2hX",
  "token_type": "Bearer",
  "user": {
    "id": 1,
    "name": "Jane Doe",
    "email": "jane@example.com",
    "created_at": "2026-06-11T12:00:00.000000Z",
    "updated_at": "2026-06-11T12:00:00.000000Z"
  }
}
```

### Login

[](#login)

```
curl -X POST http://localhost:8000/api/v1/login \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{"email": "jane@example.com", "password": "secret-password"}'
```

Returns the same `{ token, token_type, user }` shape as register. Invalid credentials return `422` with an `email` error. Login is throttled to 5 attempts per minute per email + IP.

### Logout

[](#logout)

Revokes the token used to authenticate the request.

```
curl -X POST http://localhost:8000/api/v1/logout \
  -H "Accept: application/json" \
  -H "Authorization: Bearer "
```

Returns `204 No Content`.

### Forgot password

[](#forgot-password)

```
curl -X POST http://localhost:8000/api/v1/forgot-password \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{"email": "jane@example.com"}'
```

```
{ "message": "If the email exists, a reset code has been sent." }
```

The response is identical whether or not the account exists, so callers cannot enumerate emails. When the account exists, a 6-digit code is emailed (logged, by default) and is valid for **15 minutes** (`config/auth.php` → `passwords.users.expire`).

### Reset password

[](#reset-password)

```
curl -X POST http://localhost:8000/api/v1/reset-password \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{
    "email": "jane@example.com",
    "code": "123456",
    "password": "new-secret-password",
    "password_confirmation": "new-secret-password"
  }'
```

```
{ "message": "Password has been reset." }
```

A successful reset deletes the code (single use) and **revokes every token**the user holds. A missing, expired, or wrong code always returns the same generic `422`:

```
{ "message": "...", "errors": { "code": ["The reset code is invalid or has expired."] } }
```

> **Brute-force note:** the 6-digit code is protected by throttling (5 requests per minute per email + IP), the 15-minute expiry, and single-use deletion. Tighten further (longer code, attempt counter) if your threat model needs it.

### Get the current user

[](#get-the-current-user)

```
curl http://localhost:8000/api/v1/user \
  -H "Accept: application/json" \
  -H "Authorization: Bearer "
```

```
{
  "data": {
    "id": 1,
    "name": "Jane Doe",
    "email": "jane@example.com",
    "created_at": "2026-06-11T12:00:00.000000Z",
    "updated_at": "2026-06-11T12:00:00.000000Z"
  }
}
```

### Update profile

[](#update-profile)

Send only the fields you want to change. Emails are normalized to lowercase.

```
curl -X PUT http://localhost:8000/api/v1/user \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "Authorization: Bearer " \
  -d '{"name": "Jane D.", "email": "jane.d@example.com"}'
```

Returns the updated user. Email changes take effect immediately — there is no verification flow in v1 (see [Future add-ons](#future-add-ons)).

### Change password

[](#change-password)

```
curl -X PUT http://localhost:8000/api/v1/user/password \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "Authorization: Bearer " \
  -d '{
    "current_password": "secret-password",
    "password": "new-secret-password",
    "password_confirmation": "new-secret-password"
  }'
```

```
{ "message": "Password updated." }
```

Every **other** token is revoked; the token that made the request keeps working.

### Delete account

[](#delete-account)

```
curl -X DELETE http://localhost:8000/api/v1/user \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "Authorization: Bearer " \
  -d '{"password": "secret-password"}'
```

Returns `204 No Content`. All tokens are revoked and the user row is deleted.

### List tokens

[](#list-tokens)

```
curl http://localhost:8000/api/v1/tokens \
  -H "Accept: application/json" \
  -H "Authorization: Bearer "
```

```
{
  "data": [
    {
      "id": 2,
      "name": "iphone-15",
      "abilities": ["*"],
      "last_used_at": "2026-06-11T12:34:56.000000Z",
      "created_at": "2026-06-11T12:00:00.000000Z"
    }
  ]
}
```

Token hashes are never exposed.

### Revoke one token

[](#revoke-one-token)

```
curl -X DELETE http://localhost:8000/api/v1/tokens/2 \
  -H "Accept: application/json" \
  -H "Authorization: Bearer "
```

Returns `204 No Content`, or `404` when the token does not exist or belongs to another user.

### Revoke all other tokens ("log out everywhere")

[](#revoke-all-other-tokens-log-out-everywhere)

```
curl -X DELETE http://localhost:8000/api/v1/tokens \
  -H "Accept: application/json" \
  -H "Authorization: Bearer "
```

Returns `204 No Content`. Every token except the current one is revoked.

Error shapes
------------

[](#error-shapes)

All `/api/*` errors render as JSON:

StatusBody422 validation`{ "message": "...", "errors": { "field": ["..."] } }`401 unauthenticated`{ "message": "Unauthenticated." }`404 not found`{ "message": "..." }`429 throttled`{ "message": "Too Many Attempts." }` + `Retry-After` header500`{ "message": "Server Error." }` (trace only with `APP_DEBUG=true`)Rate limiting
-------------

[](#rate-limiting)

Defined in `app/Providers/AppServiceProvider.php`:

LimiterLimitApplied to`api`60/min per user (or IP)everything else`login`5/min per email + IP`/login``password`5/min per email + IP`/forgot-password`, `/reset-password`API documentation
-----------------

[](#api-documentation)

Interactive OpenAPI 3.1 docs are generated from the code by [Scramble](https://scramble.dedoc.co):

- `GET /docs/api` — UI
- `GET /docs/api.json` — OpenAPI document

Both are restricted to the `local` environment by the `viewApiDocs` gate in `app/Providers/AppServiceProvider.php`; relax that gate to expose them elsewhere.

Token expiration
----------------

[](#token-expiration)

Tokens do not expire by default. Set `expiration` (minutes) in `config/sanctum.php` to give every token a lifetime.

CORS
----

[](#cors)

`config/cors.php` allows all origins for `api/*` — safe for token auth because no cookies or credentials are involved. Pin `allowed_origins` in production if you prefer.

Development
-----------

[](#development)

```
composer dev    # serve + queue + logs (requires npx for concurrently)
composer test   # pint --test, phpstan, pest
```

Future add-ons
--------------

[](#future-add-ons)

Deliberately not in v1, and designed to bolt on cleanly:

- **Email verification** — re-add `MustVerifyEmail` to `User` plus the verify/resend endpoints; the `email_verified_at` column already exists.
- **Two-factor authentication** (TOTP + recovery codes).
- **Social login** via Laravel Socialite.
- **OAuth2** via Laravel Passport (third-party authorization).
- **Teams / organizations**, roles &amp; permissions.

License
-------

[](#license)

The MIT License.

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance90

Actively maintained with recent releases

Popularity25

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8dfd7abe6d76f60f1fe0b5d24abd419f4945bd41766823f9134bb877bb3f5a34?d=identicon)[Laraveldaily](/maintainers/Laraveldaily)

---

Top Contributors

[![PovilasKorop](https://avatars.githubusercontent.com/u/1510147?v=4)](https://github.com/PovilasKorop "PovilasKorop (15 commits)")

---

Tags

apilaravelsanctumstarter-kit

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/laraveldaily-api-starter-kit/health.svg)

```
[![Health](https://phpackages.com/badges/laraveldaily-api-starter-kit/health.svg)](https://phpackages.com/packages/laraveldaily-api-starter-kit)
```

###  Alternatives

[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
