Skip to main content

clickup_cli/commands/
webhook.rs

1use clap::Subcommand;
2use crate::client::ClickUpClient;
3use crate::commands::auth::resolve_token;
4use crate::commands::workspace::resolve_workspace;
5use crate::error::CliError;
6use crate::output::OutputConfig;
7use crate::Cli;
8
9#[derive(Subcommand)]
10pub enum WebhookCommands {
11    /// List webhooks for the workspace
12    List,
13    /// Create a webhook
14    Create {
15        /// Endpoint URL
16        #[arg(long)]
17        endpoint: String,
18        /// Event(s) to subscribe to (can be repeated)
19        #[arg(long = "event")]
20        events: Vec<String>,
21        /// Scope to a specific space ID
22        #[arg(long)]
23        space: Option<String>,
24        /// Scope to a specific folder ID
25        #[arg(long)]
26        folder: Option<String>,
27        /// Scope to a specific list ID
28        #[arg(long)]
29        list: Option<String>,
30        /// Scope to a specific task ID
31        #[arg(long)]
32        task: Option<String>,
33    },
34    /// Update a webhook
35    Update {
36        /// Webhook ID
37        id: String,
38        /// New endpoint URL
39        #[arg(long)]
40        endpoint: String,
41        /// Event(s) to subscribe to (can be repeated)
42        #[arg(long = "event")]
43        events: Vec<String>,
44        /// Webhook status: active or inactive
45        #[arg(long, default_value = "active")]
46        status: String,
47    },
48    /// Delete a webhook
49    Delete {
50        /// Webhook ID
51        id: String,
52    },
53}
54
55const WEBHOOK_FIELDS: &[&str] = &["id", "endpoint", "status", "events"];
56
57pub async fn execute(command: WebhookCommands, cli: &Cli) -> Result<(), CliError> {
58    let token = resolve_token(cli)?;
59    let client = ClickUpClient::new(&token, cli.timeout)?;
60    let output = OutputConfig::from_cli(&cli.output, &cli.fields, cli.no_header, cli.quiet);
61
62    match command {
63        WebhookCommands::List => {
64            let ws_id = resolve_workspace(cli)?;
65            let resp = client
66                .get(&format!("/v2/team/{}/webhook", ws_id))
67                .await?;
68            let mut webhooks = resp
69                .get("webhooks")
70                .and_then(|v| v.as_array())
71                .cloned()
72                .unwrap_or_default();
73            if let Some(limit) = cli.limit {
74                webhooks.truncate(limit);
75            }
76            output.print_items(&webhooks, WEBHOOK_FIELDS, "id");
77            Ok(())
78        }
79        WebhookCommands::Create {
80            endpoint,
81            events,
82            space,
83            folder,
84            list,
85            task,
86        } => {
87            let ws_id = resolve_workspace(cli)?;
88            let mut body = serde_json::json!({
89                "endpoint": endpoint,
90                "events": events,
91            });
92            if let Some(s) = space {
93                body["space_id"] = serde_json::Value::String(s);
94            }
95            if let Some(f) = folder {
96                body["folder_id"] = serde_json::Value::String(f);
97            }
98            if let Some(l) = list {
99                body["list_id"] = serde_json::Value::String(l);
100            }
101            if let Some(t) = task {
102                body["task_id"] = serde_json::Value::String(t);
103            }
104            let resp = client
105                .post(&format!("/v2/team/{}/webhook", ws_id), &body)
106                .await?;
107            output.print_single(&resp, WEBHOOK_FIELDS, "id");
108            Ok(())
109        }
110        WebhookCommands::Update {
111            id,
112            endpoint,
113            events,
114            status,
115        } => {
116            let body = serde_json::json!({
117                "endpoint": endpoint,
118                "events": events,
119                "status": status,
120            });
121            let resp = client
122                .put(&format!("/v2/webhook/{}", id), &body)
123                .await?;
124            output.print_single(&resp, WEBHOOK_FIELDS, "id");
125            Ok(())
126        }
127        WebhookCommands::Delete { id } => {
128            client.delete(&format!("/v2/webhook/{}", id)).await?;
129            output.print_message(&format!("Webhook {} deleted", id));
130            Ok(())
131        }
132    }
133}