Labsco
github logo

typespec-api-operations

✓ Official36,200

by github · part of github/awesome-copilot

RESTful CRUD operations for TypeSpec API plugins with routing, parameters, and adaptive cards. Supports GET, POST, PATCH, and DELETE operations with path, query, and body parameters for filtering, creation, and updates Includes adaptive card visualization for GET responses and confirmation dialogs for destructive operations (POST, PATCH, DELETE) Provides complete CRUD example with models, error handling, and multiple query parameter patterns Built-in testing prompts and best practices for...

🔥🔥🔥✓ VerifiedFreeQuick setup
🧩 One of 7 skills in the github/awesome-copilot package — works on its own, and pairs well with its siblings.

RESTful CRUD operations for TypeSpec API plugins with routing, parameters, and adaptive cards. Supports GET, POST, PATCH, and DELETE operations with path, query, and body parameters for filtering, creation, and updates Includes adaptive card visualization for GET responses and confirmation dialogs for destructive operations (POST, PATCH, DELETE) Provides complete CRUD example with models, error handling, and multiple query parameter patterns Built-in testing prompts and best practices for...

Inspect the full instructions your agent will receiveExpand

This is the exact playbook injected into your agent when the skill activates — shown here so you can audit it before installing. You don't need to read it to use the skill.

by github

RESTful CRUD operations for TypeSpec API plugins with routing, parameters, and adaptive cards. Supports GET, POST, PATCH, and DELETE operations with path, query, and body parameters for filtering, creation, and updates Includes adaptive card visualization for GET responses and confirmation dialogs for destructive operations (POST, PATCH, DELETE) Provides complete CRUD example with models, error handling, and multiple query parameter patterns Built-in testing prompts and best practices for... npx skills add https://github.com/github/awesome-copilot --skill typespec-api-operations Download ZIPGitHub36.2k

Add TypeSpec API Operations

Add RESTful operations to an existing TypeSpec API plugin for Microsoft 365 Copilot.

Adding GET Operations

Simple GET - List All Items

Copy & paste — that's it
/**
 * List all items.
 */
@route("/items")
@get op listItems(): Item[];

GET with Query Parameter - Filter Results

Copy & paste — that's it
/**
 * List items filtered by criteria.
 * @param userId Optional user ID to filter items
 */
@route("/items")
@get op listItems(@query userId?: integer): Item[];

GET with Path Parameter - Get Single Item

Copy & paste — that's it
/**
 * Get a specific item by ID.
 * @param id The ID of the item to retrieve
 */
@route("/items/{id}")
@get op getItem(@path id: integer): Item;

GET with Adaptive Card

Copy & paste — that's it
/**
 * List items with adaptive card visualization.
 */
@route("/items")
@card(#{
 dataPath: "$",
 title: "$.title",
 file: "item-card.json"
})
@get op listItems(): Item[];

Create the Adaptive Card (appPackage/item-card.json):

Copy & paste — that's it
{
 "type": "AdaptiveCard",
 "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
 "version": "1.5",
 "body": [
 {
 "type": "Container",
 "$data": "${$root}",
 "items": [
 {
 "type": "TextBlock",
 "text": "**${if(title, title, 'N/A')}**",
 "wrap": true
 },
 {
 "type": "TextBlock",
 "text": "${if(description, description, 'N/A')}",
 "wrap": true
 }
 ]
 }
 ],
 "actions": [
 {
 "type": "Action.OpenUrl",
 "title": "View Details",
 "url": "https://example.com/items/${id}"
 }
 ]
}

Adding POST Operations

Simple POST - Create Item

Copy & paste — that's it
/**
 * Create a new item.
 * @param item The item to create
 */
@route("/items")
@post op createItem(@body item: CreateItemRequest): Item;

model CreateItemRequest {
 title: string;
 description?: string;
 userId: integer;
}

POST with Confirmation

Copy & paste — that's it
/**
 * Create a new item with confirmation.
 */
@route("/items")
@post
@capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Create Item",
 body: """
 Are you sure you want to create this item?
 * **Title**: {{ function.parameters.item.title }}
 * **User ID**: {{ function.parameters.item.userId }}
 """
 }
})
op createItem(@body item: CreateItemRequest): Item;

Adding PATCH Operations

Simple PATCH - Update Item

Copy & paste — that's it
/**
 * Update an existing item.
 * @param id The ID of the item to update
 * @param item The updated item data
 */
@route("/items/{id}")
@patch op updateItem(
 @path id: integer,
 @body item: UpdateItemRequest
): Item;

model UpdateItemRequest {
 title?: string;
 description?: string;
 status?: "active" | "completed" | "archived";
}

PATCH with Confirmation

Copy & paste — that's it
/**
 * Update an item with confirmation.
 */
@route("/items/{id}")
@patch
@capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Update Item",
 body: """
 Updating item #{{ function.parameters.id }}:
 * **Title**: {{ function.parameters.item.title }}
 * **Status**: {{ function.parameters.item.status }}
 """
 }
})
op updateItem(
 @path id: integer,
 @body item: UpdateItemRequest
): Item;

Adding DELETE Operations

Simple DELETE

Copy & paste — that's it
/**
 * Delete an item.
 * @param id The ID of the item to delete
 */
@route("/items/{id}")
@delete op deleteItem(@path id: integer): void;

DELETE with Confirmation

Copy & paste — that's it
/**
 * Delete an item with confirmation.
 */
@route("/items/{id}")
@delete
@capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Delete Item",
 body: """
 ⚠️ Are you sure you want to delete item #{{ function.parameters.id }}?
 This action cannot be undone.
 """
 }
})
op deleteItem(@path id: integer): void;

Complete CRUD Example

Define the Service and Models

Copy & paste — that's it
@service
@server("https://api.example.com")
@actions(#{
 nameForHuman: "Items API",
 descriptionForHuman: "Manage items",
 descriptionForModel: "Read, create, update, and delete items"
})
namespace ItemsAPI {
 
 // Models
 model Item {
 @visibility(Lifecycle.Read)
 id: integer;
 
 userId: integer;
 title: string;
 description?: string;
 status: "active" | "completed" | "archived";
 
 @format("date-time")
 createdAt: utcDateTime;
 
 @format("date-time")
 updatedAt?: utcDateTime;
 }

 model CreateItemRequest {
 userId: integer;
 title: string;
 description?: string;
 }

 model UpdateItemRequest {
 title?: string;
 description?: string;
 status?: "active" | "completed" | "archived";
 }

 // Operations
 @route("/items")
 @card(#{ dataPath: "$", title: "$.title", file: "item-card.json" })
 @get op listItems(@query userId?: integer): Item[];

 @route("/items/{id}")
 @card(#{ dataPath: "$", title: "$.title", file: "item-card.json" })
 @get op getItem(@path id: integer): Item;

 @route("/items")
 @post
 @capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Create Item",
 body: "Creating: **{{ function.parameters.item.title }}**"
 }
 })
 op createItem(@body item: CreateItemRequest): Item;

 @route("/items/{id}")
 @patch
 @capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Update Item",
 body: "Updating item #{{ function.parameters.id }}"
 }
 })
 op updateItem(@path id: integer, @body item: UpdateItemRequest): Item;

 @route("/items/{id}")
 @delete
 @capabilities(#{
 confirmation: #{
 type: "AdaptiveCard",
 title: "Delete Item",
 body: "⚠️ Delete item #{{ function.parameters.id }}?"
 }
 })
 op deleteItem(@path id: integer): void;
}

Advanced Features

Multiple Query Parameters

Copy & paste — that's it
@route("/items")
@get op listItems(
 @query userId?: integer,
 @query status?: "active" | "completed" | "archived",
 @query limit?: integer,
 @query offset?: integer
): ItemList;

model ItemList {
 items: Item[];
 total: integer;
 hasMore: boolean;
}

Header Parameters

Copy & paste — that's it
@route("/items")
@get op listItems(
 @header("X-API-Version") apiVersion?: string,
 @query userId?: integer
): Item[];

Custom Response Models

Copy & paste — that's it
@route("/items/{id}")
@delete op deleteItem(@path id: integer): DeleteResponse;

model DeleteResponse {
 success: boolean;
 message: string;
 deletedId: integer;
}

Error Responses

Copy & paste — that's it
model ErrorResponse {
 error: {
 code: string;
 message: string;
 details?: string[];
 };
}

@route("/items/{id}")
@get op getItem(@path id: integer): Item | ErrorResponse;

Testing Prompts

After adding operations, test with these prompts:

GET Operations:

  • "List all items and show them in a table"

  • "Show me items for user ID 1"

  • "Get the details of item 42"

POST Operations:

  • "Create a new item with title 'My Task' for user 1"

  • "Add an item: title 'New Feature', description 'Add login'"

PATCH Operations:

  • "Update item 10 with title 'Updated Title'"

  • "Change the status of item 5 to completed"

DELETE Operations:

  • "Delete item 99"

  • "Remove the item with ID 15"

Best Practices

Parameter Naming

  • Use descriptive parameter names: userId not uid

  • Be consistent across operations

  • Use optional parameters (?) for filters

Documentation

  • Add JSDoc comments to all operations

  • Describe what each parameter does

  • Document expected responses

Models

  • Use @visibility(Lifecycle.Read) for read-only fields like id

  • Use @format("date-time") for date fields

  • Use union types for enums: "active" | "completed"

  • Make optional fields explicit with ?

Confirmations

  • Always add confirmations to destructive operations (DELETE, PATCH)

  • Show key details in confirmation body

  • Use warning emoji (⚠️) for irreversible actions

Adaptive Cards

  • Keep cards simple and focused

  • Use conditional rendering with ${if(..., ..., 'N/A')}

  • Include action buttons for common next steps

  • Test data binding with actual API responses

Routing

  • Use RESTful conventions:

  • GET /items - List

  • GET /items/{id} - Get one

  • POST /items - Create

  • PATCH /items/{id} - Update

  • DELETE /items/{id} - Delete

  • Group related operations in the same namespace

  • Use nested routes for hierarchical resources