kayako-api-function
Scaffolds new API functions in Kayako with built-in validation and secure error handling blocks.
Install
mkdir -p .claude/skills/kayako-api-function && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12321" && unzip -o skill.zip -d .claude/skills/kayako-api-function && rm skill.zipInstalls to .claude/skills/kayako-api-function
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Adds a new procedural API function to `src/api.php` following the project's validation-first, try/catch-per-operation pattern. Initializes Kayako SOAP config, wraps each Kayako call in its own try/catch, returns status/status_text arrays. Use when user says 'add API function', 'new ticket operation', 'create endpoint in api.php', or 'add support function'. Do NOT use for modifying `src/Plugin.php` hook registration or for class-based API work.Key capabilities
- →Add new procedural API functions to src/api.php
- →Enforce validation-first input checks
- →Wrap Kayako SDK calls in individual try/catch blocks
- →Check user ownership before mutating tickets
- →Initialize Kayako SOAP configuration
- →Return status/status_text arrays on all function paths
How it works
The skill adds a new procedural API function by defining it in src/api.php, initializing a result array, validating inputs, checking ownership, initializing Kayako SOAP, and wrapping each Kayako operation in a try/catch block.
Inputs & outputs
When to use kayako-api-function
- →Adding new API endpoints
- →Creating ticket operations
- →Extending support functions
- →Implementing secure API logic
About this skill
kayako-api-function
Critical
- Never interpolate
$_GET/$_POSTdirectly into queries — always$db->real_escape($input). - Every Kayako SDK call must be in its own
try/catch (Exception $e)block — one operation per block. - Always check
$GLOBALS['tf']->ima != 'admin'ANDaccount_lidbefore any mutation that touches another user's ticket. - Always call
function_requirements('class.kyConfig')before the SOAP init try/catch — not inside it. - Return the
$resultarray on every path — never let the function fall off the end without returning.
Instructions
-
Define the function in
src/api.phpwith a PHPDoc block. Use camelCase names matching existing functions (openTicket,viewTicket,ticketPost,getTicketList)./** * One-line description. * * @param int $ticketID the ticket id * @param string $content the reply body * @return array status/status_text result */ function myNewFunction($ticketID, $content) { -
Initialize the result array as the first statement. Include only keys this function actually returns — do not add speculative keys.
$result = [ 'status' => 'incomplete', 'status_text' => '', ]; -
Validate all required inputs with early-return guards before touching Kayako. Return
'Failed'(capital F) for user-input errors.if (!$ticketID) { $result['status'] = 'Failed'; $result['status_text'] = 'Ticket Reference ID is required. Please try again!'; return $result; } if (!$content) { $result['status'] = 'Failed'; $result['status_text'] = 'Content is required. Please try again!'; return $result; }Verify all validation guards return before proceeding to Step 4.
-
Check ownership for any read/mutate of another user's ticket (skip for creation functions):
if ($GLOBALS['tf']->ima != 'admin' && $GLOBALS['tf']->accounts->data['account_lid'] != kyTicket::get($ticketID)->getUser()->getEmail()) { $result['status'] = 'Failed'; $result['status_text'] = 'Access denied. Please try again!'; myadmin_log('api', 'info', 'Denied: ' . $GLOBALS['tf']->accounts->data['account_lid'], __LINE__, __FILE__); return $result; }Wrap the ownership check itself in
try/catch—kyTicket::get()can throw. -
Initialize Kayako SOAP — call
function_requirementsoutside the try, init inside:function_requirements('class.kyConfig'); try { kyConfig::set(new kyConfig(KAYAKO_API_URL, KAYAKO_API_KEY, KAYAKO_API_SECRET)); kyConfig::get()->setDebugEnabled(false)->setTimeout(120); } catch (Exception $e) { $result['status'] = 'failed'; $result['status_text'] = 'Kayako exception occurred setting config options. Please try again!'; myadmin_log('api', 'info', $e->getMessage(), __LINE__, __FILE__); return $result; } -
Wrap each subsequent Kayako operation in its own
try/catch. Set'status_text'to a human message naming the failing operation:try { $ticket = kyTicket::get($ticketID); $user = $ticket->getUser(); } catch (Exception $e) { $result['status'] = 'Failed'; $result['status_text'] = 'Kayako exception occurred getting ticket detail. Please try again!'; myadmin_log('api', 'info', $e->getMessage(), __LINE__, __FILE__); return $result; } try { $post = $ticket->newPost($user, $content)->create(); if ($post) { $result['status'] = 'Success'; $result['status_text'] = 'Post added successfully'; } else { $result['status'] = 'Failed'; $result['status_text'] = 'Exception occurred adding post.'; } return $result; } catch (Exception $e) { $result['status'] = 'Failed'; $result['status_text'] = 'Kayako exception occurred adding post. Please try again!'; myadmin_log('api', 'info', $e->getMessage(), __LINE__, __FILE__); return $result; } } -
For DB-only functions (no Kayako, e.g. listing from
swtickets), useclone $GLOBALS['helpdesk_dbh']and always escape:$db = clone $GLOBALS['helpdesk_dbh']; $db->query("SELECT * FROM swtickets WHERE ticketmaskid = '" . $db->real_escape($ticketID) . "'", __LINE__, __FILE__); -
Run tests to verify the function exists and its signature is correct:
vendor/bin/phpunit tests/ApiFunctionsTest.phpAdd tests to
tests/ApiFunctionsTest.phpfollowing theReflectionFunctionpattern: verify function exists, parameter count, parameter names, and validation-failure return shape.
Examples
User says: "Add a function to close a ticket by ID."
Actions taken:
- Add
closeTicket($ticketID)tosrc/api.php $result = ['status' => 'incomplete', 'status_text' => '']- Guard:
if (!$ticketID)→ return'Failed' - Ownership check in try/catch
- SOAP init block
try { kyTicket::get($ticketID)->close()->save(); $result['status'] = 'Success'; ... return $result; } catch ...- Add
testCloseTicketFunctionExists,testCloseTicketSignature,testCloseTicketFailsWithEmptyIdtotests/ApiFunctionsTest.php - Run
vendor/bin/phpunit tests/ApiFunctionsTest.php
Result: New function in src/api.php, matching shape of ticketPost; tests green.
Common Issues
Call to undefined function kyConfig::set():function_requirements('class.kyConfig')was not called before the SOAP init block. Add it immediately before the try/catch.Undefined variable $resultin catch block:$resultarray was not initialized before the first if-guard. Move the$result = [...]declaration to the very first line of the function body.- Tests fail with
openTicket not found:setUpBeforeClassonly callsrequire_oncewhenopenTicketdoesn't exist. Add a stub for any new global functions your function calls (e.g.ticket_status_all) inside theif (!function_exists('openTicket'))block inApiFunctionsTest::setUpBeforeClass(). statuskey returns lowercase'failed'instead of'Failed': Validation-path failures use capital-F'Failed'; only SOAP init failures inopenTicket/getTicketListuse lowercase. Match the convention of the nearest sibling function.Undefined index: account_lid:$GLOBALS['tf']->accounts->datais not available in unit tests — wrap ownership checks in try/catch and confirm the test only exercises the pre-ownership validation paths.
When not to use it
- →For modifying src/Plugin.php hook registration
- →For class-based API work
- →When interpolating $_GET/$_POST directly into queries
Limitations
- →Does not modify src/Plugin.php
- →Does not support class-based API work
- →Requires manual addition of unit tests
How it compares
This skill enforces strict coding standards for API functions, including validation and error handling, which is more structured and secure than ad-hoc function creation.
Compared to similar skills
kayako-api-function side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| kayako-api-function (this skill) | 0 | 4mo | Review | Advanced |
| laravel-specialist | 12 | 3mo | No flags | Intermediate |
| developing-with-turbo-streams | 1 | 5mo | No flags | Intermediate |
| payment-integration | 1 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by myadmin-plugins
View all by myadmin-plugins →You might also like
laravel-specialist
Jeffallan
Use when building Laravel 10+ applications requiring Eloquent ORM, API resources, or queue systems. Invoke for Laravel models, Livewire components, Sanctum authentication, Horizon queues.
developing-with-turbo-streams
hotwired-laravel
Basics of developing with Turbo Streams in web applications. Activate when working on projects that utilize Turbo Streams for enhancing user experience through real-time updates, dynamic content changes, and partial page updates without full reloads.
payment-integration
mrgoonie
Integrate payments with SePay (VietQR), Polar, Stripe, Paddle (MoR subscriptions), Creem.io (licensing). Checkout, webhooks, subscriptions, QR codes, multi-provider orders.
developing-with-prism
prism-php
Guide for developing with Prism PHP package - a Laravel package for integrating LLMs. Activate or use when working with Prism features including text generation, structured output, embeddings, image generation, audio processing, streaming, tools/function calling, or any LLM provider integration (OpenAI, Anthropic, Gemini, Mistral, Groq, XAI, DeepSeek, OpenRouter, Ollama, VoyageAI, ElevenLabs). Activate for any Prism-related development tasks.
restapi-translations
mikopbx
Управление переводами REST API ключей (rest_*) для MikoPBX. Автоматически находит отсутствующие русские ключи в RestApi.php и синхронизирует их с исходным кодом. Использовать при проверке переводов API, после добавления новых endpoints или перед релизом.
moodle-external-api-development
davila7
Create custom external web service APIs for Moodle LMS. Use when implementing web services for course management, user tracking, quiz operations, or custom plugin functionality. Covers parameter validation, database operations, error handling, service registration, and Moodle coding standards.