Responses

The toolkit provides two response types: SuccessResponse for data and ErrorResponse for errors. Both implement Laravel's Responsable interface, so you can return them directly from controllers.

Success Responses

Single Resource

use BlueBeetle\ApiToolkit\Http\Response;

public function show(Product $product, Response $response)
{
    return $response->success($product, ProductResource::class);
}

Returns:

{
  "data": {
    "type": "products",
    "id": "1",
    "attributes": {
      "name": "Widget",
      "price": 29.99
    }
  }
}

Collections

public function index(Response $response)
{
    $products = Product::all();

    return $response->success($products, ProductResource::class);
}
return $response->success($product, ProductResource::class)
    ->meta(['request_id' => $requestId])
    ->links(['self' => route('api.products.show', $product)]);

Custom Status Code and Headers

return $response->success($product, ProductResource::class)
    ->respond(201, ['X-Custom-Header' => 'value']);

Raw Array Data

For responses that don't map to a resource, pass the data directly:

return $response->success([
    'message' => 'Import complete',
    'rows_processed' => 42,
]);

Error Responses

Basic Error

return $response->error('Not Found', 'The requested product does not exist.', 404);

Returns:

{
  "errors": [
    {
      "status": "404",
      "title": "Not Found",
      "detail": "The requested product does not exist."
    }
  ]
}

With Code and Source

return $response->error('Validation Failed', 'The name field is required.', 422)
    ->code('VALIDATION_ERROR')
    ->source(['pointer' => '/data/attributes/name']);

With Meta

return $response->error('Rate Limited', 'Too many requests.', 429)
    ->meta(['retry_after' => 60]);

Using with QueryBuilder

The QueryBuilder returns SuccessResponse instances directly:

// These all return SuccessResponse
QueryBuilder::for(Product::class, $request)
    ->fromResource(ProductResource::class)
    ->paginate();     // offset pagination

QueryBuilder::for(Product::class, $request)
    ->fromResource(ProductResource::class)
    ->cursorPaginate(); // cursor pagination

QueryBuilder::for(Product::class, $request)
    ->fromResource(ProductResource::class)
    ->get();          // all results, no pagination