api-swift / Sources / IrdAPI / Generated / P2P.swift
2,845 words
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
// Generated by scripts/gen-api.py from spec/openapi.json — do not edit.

import Foundation

// MARK: - Types

/// Shared by 5 operations.
public struct P2PNode: Codable, Sendable, Hashable {
    public var hostname: String
    public var ipv4: String?

    public init(hostname: String, ipv4: String? = nil) {
        self.hostname = hostname
        self.ipv4 = ipv4
    }

    enum CodingKeys: String, CodingKey {
        case hostname
        case ipv4
    }

    /// Explicit so required-but-nullable fields encode as `null` rather than vanishing.
    public func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(hostname, forKey: .hostname)
        try container.encode(ipv4, forKey: .ipv4)
    }
}

/// Shared by 9 operations.
public struct AppDomain: Codable, Sendable, Hashable, Identifiable {
    public var id: String
    public var hostname: String
    public var wildcard: Bool
    public var state: HostnameState
    public var dnsOk: Bool?
    public var dnsError: String?
    public var certStatus: CertStatus
    /// Point a CNAME here (the app's node hostname) for foreign-zone domains.
    public var dnsCnameTarget: String?
    public var lastError: String?
    public var createdAt: String?

    public init(id: String, hostname: String, wildcard: Bool, state: HostnameState, dnsOk: Bool? = nil, dnsError: String? = nil, certStatus: CertStatus, dnsCnameTarget: String? = nil, lastError: String? = nil, createdAt: String? = nil) {
        self.id = id
        self.hostname = hostname
        self.wildcard = wildcard
        self.state = state
        self.dnsOk = dnsOk
        self.dnsError = dnsError
        self.certStatus = certStatus
        self.dnsCnameTarget = dnsCnameTarget
        self.lastError = lastError
        self.createdAt = createdAt
    }

    enum CodingKeys: String, CodingKey {
        case id
        case hostname
        case wildcard
        case state
        case dnsOk = "dns_ok"
        case dnsError = "dns_error"
        case certStatus = "cert_status"
        case dnsCnameTarget = "dns_cname_target"
        case lastError = "last_error"
        case createdAt = "created_at"
    }

    /// Explicit so required-but-nullable fields encode as `null` rather than vanishing.
    public func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(hostname, forKey: .hostname)
        try container.encode(wildcard, forKey: .wildcard)
        try container.encode(state, forKey: .state)
        try container.encode(dnsOk, forKey: .dnsOk)
        try container.encode(dnsError, forKey: .dnsError)
        try container.encode(certStatus, forKey: .certStatus)
        try container.encode(dnsCnameTarget, forKey: .dnsCnameTarget)
        try container.encode(lastError, forKey: .lastError)
        try container.encode(createdAt, forKey: .createdAt)
    }
}

/// Shared by 5 operations.
public struct P2PApp: Codable, Sendable, Hashable, Identifiable {
    public var id: String
    public var name: String
    /// The default public hostname, `<name>.ap2p.ro`.
    public var hostname: String
    /// The WebSocket signaling relay (`wss://<hostname>/ws`).
    public var signalingUrl: String
    /// Node-local TURN credential mint (`https://<hostname>/turn-credentials`), origin-checked against the app's allowlist.
    public var turnCredentialsUrl: String
    public var iceUrls: [String]
    /// Whether the app's libp2p circuit-relay-v2 host is on (default true; relayed bytes bill at `per_mb_relayed`).
    public var relayEnabled: Bool
    /// The relay's libp2p peer id (`12D3Koo...`), derived on the node from the app's stable identity — null until the node's first report.
    public var relayPeerId: String?
    /// Dialable relay multiaddrs (`/dns4/<host>/tcp/443/tls/ws/p2p/<peer-id>`) for the default hostname and each active non-wildcard custom domain; empty until the peer id is reported or while the relay is disabled. Browser peers listen on `<multiaddr>/p2p-circuit`.
    public var relayMultiaddrs: [String]
    /// Whether the app's offline mailbox is on (default false). Peers deposit end-to-end encrypted payloads for rooms and replay them on reconnect; cached bytes bill at `per_mb_hour_cached` and deposits/replays at `per_mb_relayed`.
    public var mailboxEnabled: Bool
    /// Whether end-user peers may mint mailbox tokens straight from the node (origin-checked, default true). Turn it off to mint only through POST /p2p/apps/{id}/mailbox-credentials from your own backend — the only option for non-browser peers, which send no Origin header.
    public var mailboxOpenMint: Bool
    /// Base URL of the app's mailbox API (`https://<hostname>/mailbox/v1`); null while the mailbox is off or the node has not acked the app yet.
    public var mailboxUrl: String?
    public var state: GatewayDomainState
    /// WebSocket origin allowlist (exact origins or `*.domain.tld` wildcards); empty = any origin.
    public var origins: [String]
    public var settings: [String: Int]
    public var node: P2PNode?
    public var domains: [AppDomain]
    public var lastError: String?
    public var subscriptionId: String?
    public var createdAt: String?
    public var updatedAt: String?

    public init(id: String, name: String, hostname: String, signalingUrl: String, turnCredentialsUrl: String, iceUrls: [String], relayEnabled: Bool, relayPeerId: String? = nil, relayMultiaddrs: [String], mailboxEnabled: Bool, mailboxOpenMint: Bool, mailboxUrl: String? = nil, state: GatewayDomainState, origins: [String], settings: [String: Int], node: P2PNode? = nil, domains: [AppDomain], lastError: String? = nil, subscriptionId: String? = nil, createdAt: String? = nil, updatedAt: String? = nil) {
        self.id = id
        self.name = name
        self.hostname = hostname
        self.signalingUrl = signalingUrl
        self.turnCredentialsUrl = turnCredentialsUrl
        self.iceUrls = iceUrls
        self.relayEnabled = relayEnabled
        self.relayPeerId = relayPeerId
        self.relayMultiaddrs = relayMultiaddrs
        self.mailboxEnabled = mailboxEnabled
        self.mailboxOpenMint = mailboxOpenMint
        self.mailboxUrl = mailboxUrl
        self.state = state
        self.origins = origins
        self.settings = settings
        self.node = node
        self.domains = domains
        self.lastError = lastError
        self.subscriptionId = subscriptionId
        self.createdAt = createdAt
        self.updatedAt = updatedAt
    }

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case hostname
        case signalingUrl = "signaling_url"
        case turnCredentialsUrl = "turn_credentials_url"
        case iceUrls = "ice_urls"
        case relayEnabled = "relay_enabled"
        case relayPeerId = "relay_peer_id"
        case relayMultiaddrs = "relay_multiaddrs"
        case mailboxEnabled = "mailbox_enabled"
        case mailboxOpenMint = "mailbox_open_mint"
        case mailboxUrl = "mailbox_url"
        case state
        case origins
        case settings
        case node
        case domains
        case lastError = "last_error"
        case subscriptionId = "subscription_id"
        case createdAt = "created_at"
        case updatedAt = "updated_at"
    }

    /// Explicit so required-but-nullable fields encode as `null` rather than vanishing.
    public func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(name, forKey: .name)
        try container.encode(hostname, forKey: .hostname)
        try container.encode(signalingUrl, forKey: .signalingUrl)
        try container.encode(turnCredentialsUrl, forKey: .turnCredentialsUrl)
        try container.encode(iceUrls, forKey: .iceUrls)
        try container.encode(relayEnabled, forKey: .relayEnabled)
        try container.encode(relayPeerId, forKey: .relayPeerId)
        try container.encode(relayMultiaddrs, forKey: .relayMultiaddrs)
        try container.encode(mailboxEnabled, forKey: .mailboxEnabled)
        try container.encode(mailboxOpenMint, forKey: .mailboxOpenMint)
        try container.encode(mailboxUrl, forKey: .mailboxUrl)
        try container.encode(state, forKey: .state)
        try container.encode(origins, forKey: .origins)
        try container.encode(settings, forKey: .settings)
        try container.encode(node, forKey: .node)
        try container.encode(domains, forKey: .domains)
        try container.encode(lastError, forKey: .lastError)
        try container.encode(subscriptionId, forKey: .subscriptionId)
        try container.encode(createdAt, forKey: .createdAt)
        try container.encode(updatedAt, forKey: .updatedAt)
    }
}

/// Used by GET /p2p/apps.
public struct ListAppsResponse: Codable, Sendable, Hashable {
    public var apps: [P2PApp]

    public init(apps: [P2PApp]) {
        self.apps = apps
    }

    enum CodingKeys: String, CodingKey {
        case apps
    }
}

/// Used by POST /p2p/apps.
public struct CreateAppBody: Codable, Sendable, Hashable {
    public var name: String
    public var origins: [String]?
    public var settings: [String: Int]?
    public var mailboxEnabled: Bool?

    public init(name: String, origins: [String]? = nil, settings: [String: Int]? = nil, mailboxEnabled: Bool? = nil) {
        self.name = name
        self.origins = origins
        self.settings = settings
        self.mailboxEnabled = mailboxEnabled
    }

    enum CodingKeys: String, CodingKey {
        case name
        case origins
        case settings
        case mailboxEnabled = "mailbox_enabled"
    }
}

/// Shared by 4 operations.
public struct AppResponse: Codable, Sendable, Hashable {
    public var app: P2PApp

    public init(app: P2PApp) {
        self.app = app
    }

    enum CodingKeys: String, CodingKey {
        case app
    }
}

/// Used by PATCH /p2p/apps/{id}.
public struct UpdateAppBody: Codable, Sendable, Hashable {
    public var origins: [String]?
    public var settings: [String: Int]?
    public var relayEnabled: Bool?
    public var mailboxEnabled: Bool?
    public var mailboxOpenMint: Bool?

    public init(origins: [String]? = nil, settings: [String: Int]? = nil, relayEnabled: Bool? = nil, mailboxEnabled: Bool? = nil, mailboxOpenMint: Bool? = nil) {
        self.origins = origins
        self.settings = settings
        self.relayEnabled = relayEnabled
        self.mailboxEnabled = mailboxEnabled
        self.mailboxOpenMint = mailboxOpenMint
    }

    enum CodingKeys: String, CodingKey {
        case origins
        case settings
        case relayEnabled = "relay_enabled"
        case mailboxEnabled = "mailbox_enabled"
        case mailboxOpenMint = "mailbox_open_mint"
    }
}

/// Used by POST /p2p/apps/{id}/turn-credentials.
public struct MintTurnCredentialsBody: Codable, Sendable, Hashable {
    public var ttlSec: Int?

    public init(ttlSec: Int? = nil) {
        self.ttlSec = ttlSec
    }

    enum CodingKeys: String, CodingKey {
        case ttlSec = "ttl_sec"
    }
}

/// Used by POST /p2p/apps/{id}/turn-credentials.
public struct TurnCredentials: Codable, Sendable, Hashable {
    /// `<unix_expiry>:<app_id>` — coturn's REST credential convention.
    public var username: String
    public var credential: String
    public var ttl: Int
    public var urls: [String]

    public init(username: String, credential: String, ttl: Int, urls: [String]) {
        self.username = username
        self.credential = credential
        self.ttl = ttl
        self.urls = urls
    }

    enum CodingKeys: String, CodingKey {
        case username
        case credential
        case ttl
        case urls
    }
}

/// Used by POST /p2p/apps/{id}/turn-credentials.
public struct MintTurnCredentialsResponse: Codable, Sendable, Hashable {
    public var credentials: TurnCredentials

    public init(credentials: TurnCredentials) {
        self.credentials = credentials
    }

    enum CodingKeys: String, CodingKey {
        case credentials
    }
}

/// Used by POST /p2p/apps/{id}/mailbox-credentials.
public struct MintMailboxCredentialsBody: Codable, Sendable, Hashable {
    public var room: String?
    public var ttlSec: Int?

    public init(room: String? = nil, ttlSec: Int? = nil) {
        self.room = room
        self.ttlSec = ttlSec
    }

    enum CodingKeys: String, CodingKey {
        case room
        case ttlSec = "ttl_sec"
    }
}

/// Used by POST /p2p/apps/{id}/mailbox-credentials.
public struct MailboxCredentials: Codable, Sendable, Hashable {
    /// Bearer token for the mailbox API: `<unix_expiry>:<app_id>:<nonce>:<base64url room>.<HMAC-SHA1>`. Send it as `Authorization: Bearer <token>`.
    public var token: String
    public var ttl: Int
    /// Unix seconds at which the token stops being accepted.
    public var expiresAt: Int
    /// Base URL to call with this token (`https://<hostname>/mailbox/v1`).
    public var endpoint: String
    /// Present when the token is scoped to a single room; absent for an app-scoped token.
    public var room: String?

    public init(token: String, ttl: Int, expiresAt: Int, endpoint: String, room: String? = nil) {
        self.token = token
        self.ttl = ttl
        self.expiresAt = expiresAt
        self.endpoint = endpoint
        self.room = room
    }

    enum CodingKeys: String, CodingKey {
        case token
        case ttl
        case expiresAt = "expires_at"
        case endpoint
        case room
    }
}

/// Used by POST /p2p/apps/{id}/mailbox-credentials.
public struct MintMailboxCredentialsResponse: Codable, Sendable, Hashable {
    public var credentials: MailboxCredentials

    public init(credentials: MailboxCredentials) {
        self.credentials = credentials
    }

    enum CodingKeys: String, CodingKey {
        case credentials
    }
}

/// Used by GET /p2p/apps/{id}/domains.
public struct ListAppDomainsResponse: Codable, Sendable, Hashable {
    public var domains: [AppDomain]

    public init(domains: [AppDomain]) {
        self.domains = domains
    }

    enum CodingKeys: String, CodingKey {
        case domains
    }
}

/// Used by POST /p2p/apps/{id}/domains.
public struct P2PAttachDomainBody: Codable, Sendable, Hashable {
    public var hostname: String
    public var wildcard: Bool?

    public init(hostname: String, wildcard: Bool? = nil) {
        self.hostname = hostname
        self.wildcard = wildcard
    }

    enum CodingKeys: String, CodingKey {
        case hostname
        case wildcard
    }
}

/// Shared by 3 operations.
public struct DomainResponse: Codable, Sendable, Hashable {
    public var domain: AppDomain

    public init(domain: AppDomain) {
        self.domain = domain
    }

    enum CodingKeys: String, CodingKey {
        case domain
    }
}

/// Used by GET /p2p/usage.
public struct P2PUsage: Codable, Sendable, Hashable {
    public var apps: Int
    /// Relayed traffic (TURN + libp2p circuit relay + mailbox deposits and replays) accumulated in the current billing period (not yet billed).
    public var relayedBytesPeriod: Int
    /// Total signaling bytes observed for your apps — all-time meter, free at launch.
    public var signalBytesTotal: Int
    /// Deprecated alias of signal_bytes_total (the meter was first shipped under a _period name it never had — same all-time value).
    public var signalBytesPeriod: Int
    /// Total libp2p circuit-relay bytes observed for your apps (all-time meter; the billable period accumulation is in relayed_bytes_period).
    public var relayBytesTotal: Int
    /// Total mailbox deposit/replay bytes observed for your apps (all-time meter; the billable period accumulation is folded into relayed_bytes_period).
    public var mailboxBytesTotal: Int
    /// Mailbox bytes cached on the nodes right now. A level, not an accumulation: it is what you are being billed per MiB-hour to hold, and it falls as messages expire.
    public var cachedBytes: Int
    public var perHour: String
    public var perMbRelayed: String
    public var perMbHourCached: String
    public var hourlyCost: String
    public var monthlyEstimate: String

    public init(apps: Int, relayedBytesPeriod: Int, signalBytesTotal: Int, signalBytesPeriod: Int, relayBytesTotal: Int, mailboxBytesTotal: Int, cachedBytes: Int, perHour: String, perMbRelayed: String, perMbHourCached: String, hourlyCost: String, monthlyEstimate: String) {
        self.apps = apps
        self.relayedBytesPeriod = relayedBytesPeriod
        self.signalBytesTotal = signalBytesTotal
        self.signalBytesPeriod = signalBytesPeriod
        self.relayBytesTotal = relayBytesTotal
        self.mailboxBytesTotal = mailboxBytesTotal
        self.cachedBytes = cachedBytes
        self.perHour = perHour
        self.perMbRelayed = perMbRelayed
        self.perMbHourCached = perMbHourCached
        self.hourlyCost = hourlyCost
        self.monthlyEstimate = monthlyEstimate
    }

    enum CodingKeys: String, CodingKey {
        case apps
        case relayedBytesPeriod = "relayed_bytes_period"
        case signalBytesTotal = "signal_bytes_total"
        case signalBytesPeriod = "signal_bytes_period"
        case relayBytesTotal = "relay_bytes_total"
        case mailboxBytesTotal = "mailbox_bytes_total"
        case cachedBytes = "cached_bytes"
        case perHour = "per_hour"
        case perMbRelayed = "per_mb_relayed"
        case perMbHourCached = "per_mb_hour_cached"
        case hourlyCost = "hourly_cost"
        case monthlyEstimate = "monthly_estimate"
    }
}

/// Used by GET /p2p/usage.
public struct P2PUsageResponse: Codable, Sendable, Hashable {
    public var usage: P2PUsage

    public init(usage: P2PUsage) {
        self.usage = usage
    }

    enum CodingKeys: String, CodingKey {
        case usage
    }
}

// MARK: - Operations

extension IrdOperation {
    public static let p2p_listApps = IrdOperation(method: .get, pathTemplate: "/p2p/apps", module: "p2p", name: "listApps", security: .keyOrJwt)
    public static let p2p_createApp = IrdOperation(method: .post, pathTemplate: "/p2p/apps", module: "p2p", name: "createApp", security: .keyOrJwt)
    public static let p2p_getApp = IrdOperation(method: .get, pathTemplate: "/p2p/apps/{id}", module: "p2p", name: "getApp", security: .keyOrJwt)
    public static let p2p_deleteApp = IrdOperation(method: .delete, pathTemplate: "/p2p/apps/{id}", module: "p2p", name: "deleteApp", security: .keyOrJwt)
    public static let p2p_updateApp = IrdOperation(method: .patch, pathTemplate: "/p2p/apps/{id}", module: "p2p", name: "updateApp", security: .keyOrJwt)
    public static let p2p_mintTurnCredentials = IrdOperation(method: .post, pathTemplate: "/p2p/apps/{id}/turn-credentials", module: "p2p", name: "mintTurnCredentials", security: .keyOrJwt)
    public static let p2p_mintMailboxCredentials = IrdOperation(method: .post, pathTemplate: "/p2p/apps/{id}/mailbox-credentials", module: "p2p", name: "mintMailboxCredentials", security: .keyOrJwt)
    public static let p2p_listAppDomains = IrdOperation(method: .get, pathTemplate: "/p2p/apps/{id}/domains", module: "p2p", name: "listAppDomains", security: .keyOrJwt)
    public static let p2p_attachDomain = IrdOperation(method: .post, pathTemplate: "/p2p/apps/{id}/domains", module: "p2p", name: "attachDomain", security: .keyOrJwt)
    public static let p2p_detachDomain = IrdOperation(method: .delete, pathTemplate: "/p2p/apps/{id}/domains/{domain-id}", module: "p2p", name: "detachDomain", security: .keyOrJwt)
    public static let p2p_verifyDomainDns = IrdOperation(method: .post, pathTemplate: "/p2p/apps/{id}/domains/{domain-id}/verify-dns", module: "p2p", name: "verifyDomainDns", security: .keyOrJwt)
    public static let p2p_usage = IrdOperation(method: .get, pathTemplate: "/p2p/usage", module: "p2p", name: "usage", security: .keyOrJwt)

    static let p2pOperations: [IrdOperation] = [.p2p_listApps, .p2p_createApp, .p2p_getApp, .p2p_deleteApp, .p2p_updateApp, .p2p_mintTurnCredentials, .p2p_mintMailboxCredentials, .p2p_listAppDomains, .p2p_attachDomain, .p2p_detachDomain, .p2p_verifyDomainDns, .p2p_usage]
}

/// The `p2p` operations (12).
public struct P2PAPI: Sendable {
    let client: IrdClient

    /// List your p2p apps
    /// Every non-deleted p2p app on the account, custom domains embedded. Charged `p2p.reads` per request.
    /// `GET /p2p/apps` — 200
    public func listApps() async throws -> ListAppsResponse {
        try await client.request(.p2p_listApps)
    }

    /// Create a p2p app
    /// Provisions a managed WebSocket signaling relay + STUN/TURN + libp2p circuit-relay-v2 at `<name>.ap2p.ro`: a node is assigned, the first prepaid hour is charged (`recurring.p2p-app-hourly` — billing continues hourly at `per_hour` plus `per_m…
    /// `POST /p2p/apps` — 201
    public func createApp(body: CreateAppBody) async throws -> AppResponse {
        try await client.request(.p2p_createApp, body: body)
    }

    /// P2P app detail
    /// One app with its connection URLs, node and custom domains. Charged `p2p.reads` per request.
    /// `GET /p2p/apps/{id}` — 200
    public func getApp(id: String) async throws -> AppResponse {
        try await client.request(.p2p_getApp, params: ["id": id])
    }

    /// Delete a p2p app
    /// Stops billing immediately and tears the app (and its custom domains) down on the node's next poll. Free — a negative balance never blocks stopping the app that is billing you. Idempotent while deletion is in progress.
    /// `DELETE /p2p/apps/{id}` — 200
    public func deleteApp(id: String) async throws -> AppResponse {
        try await client.request(.p2p_deleteApp, params: ["id": id])
    }

    /// Update app origins/settings/relay/mailbox
    /// Replaces the app's origin allowlist and/or limit settings — each provided key is a full replace (send `origins: []` to allow any origin again; omit a key to leave it untouched) — and/or flips the libp2p circuit relay with `relay_enabled`.
    /// `PATCH /p2p/apps/{id}` — 200
    public func updateApp(id: String, body: UpdateAppBody? = nil) async throws -> AppResponse {
        try await client.request(.p2p_updateApp, params: ["id": id], body: body)
    }

    /// Mint TURN credentials
    /// Mints short-lived TURN credentials for the app (coturn REST convention: username `<unix_expiry>:<app_id>`, HMAC-SHA1 credential) plus the node's ICE server URLs.
    /// `POST /p2p/apps/{id}/turn-credentials` — 200
    public func mintTurnCredentials(id: String, body: MintTurnCredentialsBody? = nil) async throws -> MintTurnCredentialsResponse {
        try await client.request(.p2p_mintTurnCredentials, params: ["id": id], body: body)
    }

    /// Mint a mailbox token
    /// Mints a short-lived bearer token for the app's offline mailbox (HMAC-SHA1 over the node secret, the same derivation as TURN).
    /// `POST /p2p/apps/{id}/mailbox-credentials` — 200
    public func mintMailboxCredentials(id: String, body: MintMailboxCredentialsBody? = nil) async throws -> MintMailboxCredentialsResponse {
        try await client.request(.p2p_mintMailboxCredentials, params: ["id": id], body: body)
    }

    /// List an app's custom domains
    /// The app's non-deleted custom domains. Charged `p2p.reads` per request.
    /// `GET /p2p/apps/{id}/domains` — 200
    public func listAppDomains(id: String) async throws -> ListAppDomainsResponse {
        try await client.request(.p2p_listAppDomains, params: ["id": id])
    }

    /// Attach a custom domain
    /// Attaches your own hostname to the app on top of the default `<name>.ap2p.ro`.
    /// `POST /p2p/apps/{id}/domains` — 201
    public func attachDomain(id: String, body: P2PAttachDomainBody) async throws -> DomainResponse {
        try await client.request(.p2p_attachDomain, params: ["id": id], body: body)
    }

    /// Detach a custom domain
    /// Detaches the domain — the node drops its vhost on the next poll and the auto-created DNS record on your ird-hosted zone is removed. Free; idempotent while deletion is in progress.
    /// `DELETE /p2p/apps/{id}/domains/{domain-id}` — 200
    public func detachDomain(id: String, domainId: String) async throws -> DomainResponse {
        try await client.request(.p2p_detachDomain, params: ["id": id, "domain-id": domainId])
    }

    /// Re-check a domain's DNS
    /// Re-verifies that the hostname resolves to the app's node (run it after fixing your records — a pass also retries a failed certificate; wildcards verify through a probe label). Charged `p2p.reads` per request.
    /// `POST /p2p/apps/{id}/domains/{domain-id}/verify-dns` — 200
    public func verifyDomainDns(id: String, domainId: String) async throws -> DomainResponse {
        try await client.request(.p2p_verifyDomainDns, params: ["id": id, "domain-id": domainId])
    }

    /// P2P usage and cost
    /// Live app count, TURN relay bytes accumulated this billing period (billed `per_mb_relayed` at the next hourly settle), total signaling bytes observed (metered, free at launch), the active `recurring.p2p-app-hourly` rates and the cost project…
    /// `GET /p2p/usage` — 200
    public func usage() async throws -> P2PUsageResponse {
        try await client.request(.p2p_usage)
    }
}

extension IrdClient {
    public var p2p: P2PAPI { P2PAPI(client: self) }
}

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/api-swift.git