repull 0.2.32 → 0.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/repull/api/connections_api.rb +77 -0
  4. data/lib/repull/api/resolutions_api.rb +236 -0
  5. data/lib/repull/api/transactions_api.rb +73 -0
  6. data/lib/repull/models/account_import.rb +237 -0
  7. data/lib/repull/models/account_import_completed_event.rb +282 -0
  8. data/lib/repull/models/account_import_counts.rb +193 -0
  9. data/lib/repull/models/account_import_failed_event.rb +282 -0
  10. data/lib/repull/models/account_import_finished_payload.rb +224 -0
  11. data/lib/repull/models/account_import_stage.rb +177 -0
  12. data/lib/repull/models/account_import_started_event.rb +282 -0
  13. data/lib/repull/models/account_import_started_payload.rb +177 -0
  14. data/lib/repull/models/connection.rb +16 -5
  15. data/lib/repull/models/list_airbnb_resolutions200_response.rb +192 -0
  16. data/lib/repull/models/list_connection_imports200_response.rb +158 -0
  17. data/lib/repull/models/refresh_airbnb_resolutions200_response.rb +219 -0
  18. data/lib/repull/models/refresh_airbnb_resolutions200_response_accounts_inner.rb +200 -0
  19. data/lib/repull/models/refresh_airbnb_resolutions200_response_accounts_inner_error.rb +156 -0
  20. data/lib/repull/models/refresh_airbnb_resolutions_request.rb +192 -0
  21. data/lib/repull/models/resolution.rb +329 -0
  22. data/lib/repull/models/transaction_payout.rb +17 -6
  23. data/lib/repull/models/webhook_event.rb +6 -0
  24. data/lib/repull/models/webhook_event_type.rb +4 -1
  25. data/lib/repull/version.rb +1 -1
  26. data/lib/repull.rb +16 -0
  27. data/openapi/v1.json +845 -78
  28. data/scripts/regen.sh +1 -1
  29. metadata +18 -2
data/openapi/v1.json CHANGED
@@ -62,6 +62,10 @@
62
62
  "name": "Transactions",
63
63
  "description": "Unified transactions & payments ledger across channels \u2014 payouts, reservation charges, refunds. `booking` covers Booking.com however it was connected."
64
64
  },
65
+ {
66
+ "name": "Resolutions",
67
+ "description": "Airbnb Resolution Center cases (AirCover / damage, extra-guest, refund and change requests) \u2014 read-only visibility on open and closed resolutions. The money a resolution moved is in the transactions ledger; join on the resolution id."
68
+ },
65
69
  {
66
70
  "name": "Availability",
67
71
  "description": "Check and update property availability and pricing"
@@ -1544,6 +1548,15 @@
1544
1548
  "format": "uri",
1545
1549
  "nullable": true,
1546
1550
  "description": "Durable link that reopens the hosted Connect flow bound to this account on the fix screen \u2014 send the host here to resolve `action`. Present only when `action.required` is true; `null` otherwise."
1551
+ },
1552
+ "import": {
1553
+ "allOf": [
1554
+ {
1555
+ "$ref": "#/components/schemas/AccountImport"
1556
+ }
1557
+ ],
1558
+ "nullable": true,
1559
+ "description": "The account's latest import \u2014 `status: running` while the first sync (or a later one) is going, then `completed` or `failed`. `null` when no import has been recorded. The same run is announced by the `account.import.*` webhooks; the history is on `GET /v1/connections/{id}/imports`."
1547
1560
  }
1548
1561
  }
1549
1562
  },
@@ -2673,6 +2686,9 @@
2673
2686
  "account.created",
2674
2687
  "connect.session.completed",
2675
2688
  "account.disconnected",
2689
+ "account.import.started",
2690
+ "account.import.completed",
2691
+ "account.import.failed",
2676
2692
  "review.created",
2677
2693
  "review.responded",
2678
2694
  "ai.operation.completed",
@@ -4890,7 +4906,165 @@
4890
4906
  }
4891
4907
  }
4892
4908
  },
4893
- "ConnectSessionCompletedEvent": {
4909
+ "AccountImportStage": {
4910
+ "type": "object",
4911
+ "description": "One stage of an account import (e.g. `reservations`). The stage is done when `done + failed` reaches `expected`.",
4912
+ "properties": {
4913
+ "name": {
4914
+ "type": "string",
4915
+ "example": "reservations"
4916
+ },
4917
+ "expected": {
4918
+ "type": "integer",
4919
+ "nullable": true,
4920
+ "description": "Units of work in this stage (one per page, chunk, listing or thread, depending on the channel). `null` until the stage knows its size."
4921
+ },
4922
+ "done": {
4923
+ "type": "integer"
4924
+ },
4925
+ "failed": {
4926
+ "type": "integer"
4927
+ }
4928
+ }
4929
+ },
4930
+ "AccountImportCounts": {
4931
+ "type": "object",
4932
+ "description": "What the import brought in. A channel reports the keys it imports.",
4933
+ "properties": {
4934
+ "listings": {
4935
+ "type": "integer"
4936
+ },
4937
+ "reservations": {
4938
+ "type": "integer"
4939
+ },
4940
+ "conversations": {
4941
+ "type": "integer"
4942
+ },
4943
+ "messages": {
4944
+ "type": "integer"
4945
+ },
4946
+ "reviews": {
4947
+ "type": "integer"
4948
+ },
4949
+ "payments": {
4950
+ "type": "integer"
4951
+ }
4952
+ }
4953
+ },
4954
+ "AccountImport": {
4955
+ "type": "object",
4956
+ "description": "One import run of a connected account: the first sync after connecting, a room or unit mapped later, a reconnect or a re-sync.",
4957
+ "properties": {
4958
+ "id": {
4959
+ "type": "string",
4960
+ "format": "uuid",
4961
+ "description": "The import id \u2014 the `importId` on `account.import.*` webhooks."
4962
+ },
4963
+ "status": {
4964
+ "type": "string"
4965
+ },
4966
+ "trigger": {
4967
+ "type": "string"
4968
+ },
4969
+ "outcome": {
4970
+ "type": "string",
4971
+ "nullable": true,
4972
+ "description": "`completed` imports only: `partial` when some units failed (see `stages`)."
4973
+ },
4974
+ "reason": {
4975
+ "type": "string",
4976
+ "nullable": true,
4977
+ "description": "`failed` imports only: why it stopped \u2014 e.g. `needs_permissions`, `duplicate_account`, `stalled`."
4978
+ },
4979
+ "startedAt": {
4980
+ "type": "string",
4981
+ "format": "date-time"
4982
+ },
4983
+ "lastActivityAt": {
4984
+ "type": "string",
4985
+ "format": "date-time"
4986
+ },
4987
+ "completedAt": {
4988
+ "type": "string",
4989
+ "format": "date-time",
4990
+ "nullable": true
4991
+ },
4992
+ "stages": {
4993
+ "type": "array",
4994
+ "items": {
4995
+ "$ref": "#/components/schemas/AccountImportStage"
4996
+ }
4997
+ },
4998
+ "counts": {
4999
+ "$ref": "#/components/schemas/AccountImportCounts"
5000
+ }
5001
+ }
5002
+ },
5003
+ "AccountImportStartedPayload": {
5004
+ "type": "object",
5005
+ "properties": {
5006
+ "importId": {
5007
+ "type": "string",
5008
+ "format": "uuid"
5009
+ },
5010
+ "trigger": {
5011
+ "type": "string"
5012
+ },
5013
+ "startedAt": {
5014
+ "type": "string",
5015
+ "format": "date-time"
5016
+ },
5017
+ "stages": {
5018
+ "type": "array",
5019
+ "items": {
5020
+ "type": "string"
5021
+ },
5022
+ "description": "The stages this import will run."
5023
+ }
5024
+ }
5025
+ },
5026
+ "AccountImportFinishedPayload": {
5027
+ "type": "object",
5028
+ "properties": {
5029
+ "importId": {
5030
+ "type": "string",
5031
+ "format": "uuid"
5032
+ },
5033
+ "trigger": {
5034
+ "type": "string"
5035
+ },
5036
+ "status": {
5037
+ "type": "string"
5038
+ },
5039
+ "outcome": {
5040
+ "type": "string",
5041
+ "nullable": true
5042
+ },
5043
+ "startedAt": {
5044
+ "type": "string",
5045
+ "format": "date-time"
5046
+ },
5047
+ "completedAt": {
5048
+ "type": "string",
5049
+ "format": "date-time"
5050
+ },
5051
+ "stages": {
5052
+ "type": "array",
5053
+ "items": {
5054
+ "$ref": "#/components/schemas/AccountImportStage"
5055
+ }
5056
+ },
5057
+ "counts": {
5058
+ "$ref": "#/components/schemas/AccountImportCounts"
5059
+ },
5060
+ "reason": {
5061
+ "type": "string",
5062
+ "nullable": true,
5063
+ "description": "`account.import.failed` only."
5064
+ }
5065
+ }
5066
+ },
5067
+ "AccountImportStartedEvent": {
4894
5068
  "type": "object",
4895
5069
  "required": [
4896
5070
  "event",
@@ -4922,11 +5096,12 @@
4922
5096
  "$ref": "#/components/schemas/WebhookEventAccount"
4923
5097
  },
4924
5098
  "data": {
4925
- "$ref": "#/components/schemas/ConnectSessionCompletedPayload"
5099
+ "$ref": "#/components/schemas/AccountImportStartedPayload"
4926
5100
  }
4927
- }
5101
+ },
5102
+ "description": "An account import began."
4928
5103
  },
4929
- "AccountDisconnectedEvent": {
5104
+ "AccountImportCompletedEvent": {
4930
5105
  "type": "object",
4931
5106
  "required": [
4932
5107
  "event",
@@ -4958,11 +5133,12 @@
4958
5133
  "$ref": "#/components/schemas/WebhookEventAccount"
4959
5134
  },
4960
5135
  "data": {
4961
- "$ref": "#/components/schemas/AccountDisconnectedPayload"
5136
+ "$ref": "#/components/schemas/AccountImportFinishedPayload"
4962
5137
  }
4963
- }
5138
+ },
5139
+ "description": "Every stage of an account import finished. Its data is readable through the API."
4964
5140
  },
4965
- "ReviewCreatedEvent": {
5141
+ "AccountImportFailedEvent": {
4966
5142
  "type": "object",
4967
5143
  "required": [
4968
5144
  "event",
@@ -4994,11 +5170,12 @@
4994
5170
  "$ref": "#/components/schemas/WebhookEventAccount"
4995
5171
  },
4996
5172
  "data": {
4997
- "$ref": "#/components/schemas/ReviewCreatedPayload"
5173
+ "$ref": "#/components/schemas/AccountImportFinishedPayload"
4998
5174
  }
4999
- }
5175
+ },
5176
+ "description": "An account import stopped before finishing; `data.reason` says why."
5000
5177
  },
5001
- "ReviewRespondedEvent": {
5178
+ "ConnectSessionCompletedEvent": {
5002
5179
  "type": "object",
5003
5180
  "required": [
5004
5181
  "event",
@@ -5030,11 +5207,11 @@
5030
5207
  "$ref": "#/components/schemas/WebhookEventAccount"
5031
5208
  },
5032
5209
  "data": {
5033
- "$ref": "#/components/schemas/ReviewRespondedPayload"
5210
+ "$ref": "#/components/schemas/ConnectSessionCompletedPayload"
5034
5211
  }
5035
5212
  }
5036
5213
  },
5037
- "AiOperationCompletedEvent": {
5214
+ "AccountDisconnectedEvent": {
5038
5215
  "type": "object",
5039
5216
  "required": [
5040
5217
  "event",
@@ -5066,11 +5243,11 @@
5066
5243
  "$ref": "#/components/schemas/WebhookEventAccount"
5067
5244
  },
5068
5245
  "data": {
5069
- "$ref": "#/components/schemas/AiOperationCompletedPayload"
5246
+ "$ref": "#/components/schemas/AccountDisconnectedPayload"
5070
5247
  }
5071
5248
  }
5072
5249
  },
5073
- "AiOperationFailedEvent": {
5250
+ "ReviewCreatedEvent": {
5074
5251
  "type": "object",
5075
5252
  "required": [
5076
5253
  "event",
@@ -5102,11 +5279,11 @@
5102
5279
  "$ref": "#/components/schemas/WebhookEventAccount"
5103
5280
  },
5104
5281
  "data": {
5105
- "$ref": "#/components/schemas/AiOperationFailedPayload"
5282
+ "$ref": "#/components/schemas/ReviewCreatedPayload"
5106
5283
  }
5107
5284
  }
5108
5285
  },
5109
- "PaymentCompletedEvent": {
5286
+ "ReviewRespondedEvent": {
5110
5287
  "type": "object",
5111
5288
  "required": [
5112
5289
  "event",
@@ -5138,11 +5315,11 @@
5138
5315
  "$ref": "#/components/schemas/WebhookEventAccount"
5139
5316
  },
5140
5317
  "data": {
5141
- "$ref": "#/components/schemas/PaymentCompletedPayload"
5318
+ "$ref": "#/components/schemas/ReviewRespondedPayload"
5142
5319
  }
5143
5320
  }
5144
5321
  },
5145
- "PayoutCompletedEvent": {
5322
+ "AiOperationCompletedEvent": {
5146
5323
  "type": "object",
5147
5324
  "required": [
5148
5325
  "event",
@@ -5174,11 +5351,11 @@
5174
5351
  "$ref": "#/components/schemas/WebhookEventAccount"
5175
5352
  },
5176
5353
  "data": {
5177
- "$ref": "#/components/schemas/PayoutCompletedPayload"
5354
+ "$ref": "#/components/schemas/AiOperationCompletedPayload"
5178
5355
  }
5179
5356
  }
5180
5357
  },
5181
- "PaymentRefundedEvent": {
5358
+ "AiOperationFailedEvent": {
5182
5359
  "type": "object",
5183
5360
  "required": [
5184
5361
  "event",
@@ -5210,11 +5387,11 @@
5210
5387
  "$ref": "#/components/schemas/WebhookEventAccount"
5211
5388
  },
5212
5389
  "data": {
5213
- "$ref": "#/components/schemas/PaymentRefundedPayload"
5390
+ "$ref": "#/components/schemas/AiOperationFailedPayload"
5214
5391
  }
5215
5392
  }
5216
5393
  },
5217
- "RepullPingEvent": {
5394
+ "PaymentCompletedEvent": {
5218
5395
  "type": "object",
5219
5396
  "required": [
5220
5397
  "event",
@@ -5246,11 +5423,11 @@
5246
5423
  "$ref": "#/components/schemas/WebhookEventAccount"
5247
5424
  },
5248
5425
  "data": {
5249
- "$ref": "#/components/schemas/RepullPingPayload"
5426
+ "$ref": "#/components/schemas/PaymentCompletedPayload"
5250
5427
  }
5251
5428
  }
5252
5429
  },
5253
- "UsageQuotaWarningEvent": {
5430
+ "PayoutCompletedEvent": {
5254
5431
  "type": "object",
5255
5432
  "required": [
5256
5433
  "event",
@@ -5282,72 +5459,53 @@
5282
5459
  "$ref": "#/components/schemas/WebhookEventAccount"
5283
5460
  },
5284
5461
  "data": {
5285
- "$ref": "#/components/schemas/UsageQuotaWarningPayload"
5462
+ "$ref": "#/components/schemas/PayoutCompletedPayload"
5286
5463
  }
5287
5464
  }
5288
5465
  },
5289
- "MigrationImportPayload": {
5466
+ "PaymentRefundedEvent": {
5290
5467
  "type": "object",
5291
- "description": "One import run into a migration workspace.",
5468
+ "required": [
5469
+ "event",
5470
+ "eventId",
5471
+ "apiVersion",
5472
+ "timestamp",
5473
+ "data"
5474
+ ],
5292
5475
  "properties": {
5293
- "workspaceId": {
5294
- "type": "integer"
5295
- },
5296
- "provider": {
5476
+ "event": {
5297
5477
  "type": "string",
5298
- "example": "guesty"
5299
- },
5300
- "connectionId": {
5301
- "type": "integer"
5302
- },
5303
- "status": {
5304
- "type": "string"
5478
+ "description": "The event name. This field is `event`, not `type`."
5305
5479
  },
5306
- "startedAt": {
5480
+ "eventId": {
5307
5481
  "type": "string",
5308
- "format": "date-time"
5482
+ "format": "uuid",
5483
+ "description": "Stable across every delivery and replay of this logical event \u2014 dedupe on it."
5309
5484
  },
5310
- "finishedAt": {
5485
+ "apiVersion": {
5311
5486
  "type": "string",
5312
- "format": "date-time"
5487
+ "example": "2026-04"
5313
5488
  },
5314
- "entities": {
5315
- "type": "array",
5316
- "items": {
5317
- "type": "string"
5318
- }
5489
+ "timestamp": {
5490
+ "type": "string",
5491
+ "format": "date-time",
5492
+ "description": "When this delivery was built."
5319
5493
  },
5320
- "results": {
5321
- "type": "array",
5322
- "items": {
5323
- "type": "object",
5324
- "properties": {
5325
- "entityType": {
5326
- "type": "string"
5327
- },
5328
- "processed": {
5329
- "type": "integer"
5330
- },
5331
- "errors": {
5332
- "type": "integer"
5333
- }
5334
- }
5335
- }
5494
+ "account": {
5495
+ "$ref": "#/components/schemas/WebhookEventAccount"
5336
5496
  },
5337
- "error": {
5338
- "type": "string",
5339
- "description": "Present on `migration.failed`."
5497
+ "data": {
5498
+ "$ref": "#/components/schemas/PaymentRefundedPayload"
5340
5499
  }
5341
5500
  }
5342
5501
  },
5343
- "MigrationCompletedEvent": {
5502
+ "RepullPingEvent": {
5344
5503
  "type": "object",
5345
5504
  "required": [
5346
5505
  "event",
5347
5506
  "eventId",
5348
5507
  "apiVersion",
5349
5508
  "timestamp",
5350
- "workspaceId",
5351
5509
  "data"
5352
5510
  ],
5353
5511
  "properties": {
@@ -5372,24 +5530,151 @@
5372
5530
  "account": {
5373
5531
  "$ref": "#/components/schemas/WebhookEventAccount"
5374
5532
  },
5375
- "workspaceId": {
5376
- "type": "integer",
5377
- "description": "The migration's workspace \u2014 pass it as `X-Workspace-Id`, or to `GET /v1/migrations/{workspaceId}`."
5378
- },
5379
5533
  "data": {
5380
- "$ref": "#/components/schemas/MigrationImportPayload"
5534
+ "$ref": "#/components/schemas/RepullPingPayload"
5381
5535
  }
5382
- },
5383
- "description": "An import into a migration workspace finished."
5536
+ }
5384
5537
  },
5385
- "MigrationFailedEvent": {
5538
+ "UsageQuotaWarningEvent": {
5386
5539
  "type": "object",
5387
5540
  "required": [
5388
5541
  "event",
5389
5542
  "eventId",
5390
5543
  "apiVersion",
5391
5544
  "timestamp",
5392
- "workspaceId",
5545
+ "data"
5546
+ ],
5547
+ "properties": {
5548
+ "event": {
5549
+ "type": "string",
5550
+ "description": "The event name. This field is `event`, not `type`."
5551
+ },
5552
+ "eventId": {
5553
+ "type": "string",
5554
+ "format": "uuid",
5555
+ "description": "Stable across every delivery and replay of this logical event \u2014 dedupe on it."
5556
+ },
5557
+ "apiVersion": {
5558
+ "type": "string",
5559
+ "example": "2026-04"
5560
+ },
5561
+ "timestamp": {
5562
+ "type": "string",
5563
+ "format": "date-time",
5564
+ "description": "When this delivery was built."
5565
+ },
5566
+ "account": {
5567
+ "$ref": "#/components/schemas/WebhookEventAccount"
5568
+ },
5569
+ "data": {
5570
+ "$ref": "#/components/schemas/UsageQuotaWarningPayload"
5571
+ }
5572
+ }
5573
+ },
5574
+ "MigrationImportPayload": {
5575
+ "type": "object",
5576
+ "description": "One import run into a migration workspace.",
5577
+ "properties": {
5578
+ "workspaceId": {
5579
+ "type": "integer"
5580
+ },
5581
+ "provider": {
5582
+ "type": "string",
5583
+ "example": "guesty"
5584
+ },
5585
+ "connectionId": {
5586
+ "type": "integer"
5587
+ },
5588
+ "status": {
5589
+ "type": "string"
5590
+ },
5591
+ "startedAt": {
5592
+ "type": "string",
5593
+ "format": "date-time"
5594
+ },
5595
+ "finishedAt": {
5596
+ "type": "string",
5597
+ "format": "date-time"
5598
+ },
5599
+ "entities": {
5600
+ "type": "array",
5601
+ "items": {
5602
+ "type": "string"
5603
+ }
5604
+ },
5605
+ "results": {
5606
+ "type": "array",
5607
+ "items": {
5608
+ "type": "object",
5609
+ "properties": {
5610
+ "entityType": {
5611
+ "type": "string"
5612
+ },
5613
+ "processed": {
5614
+ "type": "integer"
5615
+ },
5616
+ "errors": {
5617
+ "type": "integer"
5618
+ }
5619
+ }
5620
+ }
5621
+ },
5622
+ "error": {
5623
+ "type": "string",
5624
+ "description": "Present on `migration.failed`."
5625
+ }
5626
+ }
5627
+ },
5628
+ "MigrationCompletedEvent": {
5629
+ "type": "object",
5630
+ "required": [
5631
+ "event",
5632
+ "eventId",
5633
+ "apiVersion",
5634
+ "timestamp",
5635
+ "workspaceId",
5636
+ "data"
5637
+ ],
5638
+ "properties": {
5639
+ "event": {
5640
+ "type": "string",
5641
+ "description": "The event name. This field is `event`, not `type`."
5642
+ },
5643
+ "eventId": {
5644
+ "type": "string",
5645
+ "format": "uuid",
5646
+ "description": "Stable across every delivery and replay of this logical event \u2014 dedupe on it."
5647
+ },
5648
+ "apiVersion": {
5649
+ "type": "string",
5650
+ "example": "2026-04"
5651
+ },
5652
+ "timestamp": {
5653
+ "type": "string",
5654
+ "format": "date-time",
5655
+ "description": "When this delivery was built."
5656
+ },
5657
+ "account": {
5658
+ "$ref": "#/components/schemas/WebhookEventAccount"
5659
+ },
5660
+ "workspaceId": {
5661
+ "type": "integer",
5662
+ "description": "The migration's workspace \u2014 pass it as `X-Workspace-Id`, or to `GET /v1/migrations/{workspaceId}`."
5663
+ },
5664
+ "data": {
5665
+ "$ref": "#/components/schemas/MigrationImportPayload"
5666
+ }
5667
+ },
5668
+ "description": "An import into a migration workspace finished."
5669
+ },
5670
+ "MigrationFailedEvent": {
5671
+ "type": "object",
5672
+ "required": [
5673
+ "event",
5674
+ "eventId",
5675
+ "apiVersion",
5676
+ "timestamp",
5677
+ "workspaceId",
5393
5678
  "data"
5394
5679
  ],
5395
5680
  "properties": {
@@ -5489,6 +5774,15 @@
5489
5774
  {
5490
5775
  "$ref": "#/components/schemas/AccountDisconnectedEvent"
5491
5776
  },
5777
+ {
5778
+ "$ref": "#/components/schemas/AccountImportStartedEvent"
5779
+ },
5780
+ {
5781
+ "$ref": "#/components/schemas/AccountImportCompletedEvent"
5782
+ },
5783
+ {
5784
+ "$ref": "#/components/schemas/AccountImportFailedEvent"
5785
+ },
5492
5786
  {
5493
5787
  "$ref": "#/components/schemas/ReviewCreatedEvent"
5494
5788
  },
@@ -5547,6 +5841,9 @@
5547
5841
  "account.created": "#/components/schemas/AccountCreatedEvent",
5548
5842
  "connect.session.completed": "#/components/schemas/ConnectSessionCompletedEvent",
5549
5843
  "account.disconnected": "#/components/schemas/AccountDisconnectedEvent",
5844
+ "account.import.started": "#/components/schemas/AccountImportStartedEvent",
5845
+ "account.import.completed": "#/components/schemas/AccountImportCompletedEvent",
5846
+ "account.import.failed": "#/components/schemas/AccountImportFailedEvent",
5550
5847
  "review.created": "#/components/schemas/ReviewCreatedEvent",
5551
5848
  "review.responded": "#/components/schemas/ReviewRespondedEvent",
5552
5849
  "ai.operation.completed": "#/components/schemas/AiOperationCompletedEvent",
@@ -7408,7 +7705,13 @@
7408
7705
  "statementUrl": {
7409
7706
  "type": "string",
7410
7707
  "nullable": true,
7411
- "description": "Link to the channel's original payout statement PDF \u2014 the authoritative settlement record (Booking.com). Null when none."
7708
+ "description": "Repull-hosted download link for the original payout statement PDF (the authoritative settlement record). Add `?format=csv` for the CSV. Served by `GET /v1/transactions/{id}/statement` \u2014 no channel session needed. Null when none is stored."
7709
+ },
7710
+ "statementId": {
7711
+ "type": "string",
7712
+ "nullable": true,
7713
+ "description": "The channel's own numeric statement id (Booking.com, e.g. \"010747030095\"). Null when none.",
7714
+ "example": "010747030095"
7412
7715
  }
7413
7716
  }
7414
7717
  },
@@ -7432,6 +7735,97 @@
7432
7735
  }
7433
7736
  }
7434
7737
  },
7738
+ "Resolution": {
7739
+ "type": "object",
7740
+ "description": "An Airbnb Resolution Center case (AirCover / damage, extra-guest, refund or change request). Read-only \u2014 Airbnb exposes no create/evidence/status API. The money a resolution moved rides in the transactions ledger as `Resolution Payout` / `Resolution Adjustment` rows sharing the same reference; join on `resolutionId`.",
7741
+ "required": [
7742
+ "resolutionId",
7743
+ "status"
7744
+ ],
7745
+ "properties": {
7746
+ "resolutionId": {
7747
+ "type": "string",
7748
+ "description": "Airbnb's resolution id \u2014 the `{id}` path value and the join key to a transaction's `reference`.",
7749
+ "example": "CLSF-06464054"
7750
+ },
7751
+ "confirmationCode": {
7752
+ "type": "string",
7753
+ "nullable": true,
7754
+ "description": "Airbnb confirmation code of the reservation the case is on.",
7755
+ "example": "HMZKMYCBC5"
7756
+ },
7757
+ "reservationId": {
7758
+ "type": "integer",
7759
+ "nullable": true,
7760
+ "description": "Repull's internal reservation id, when the reservation is in this workspace."
7761
+ },
7762
+ "listingName": {
7763
+ "type": "string",
7764
+ "nullable": true
7765
+ },
7766
+ "status": {
7767
+ "type": "string",
7768
+ "nullable": true,
7769
+ "description": "OPEN or CLOSED, as Airbnb reports it.",
7770
+ "example": "OPEN"
7771
+ },
7772
+ "reason": {
7773
+ "type": "string",
7774
+ "nullable": true,
7775
+ "description": "Why the resolution was opened."
7776
+ },
7777
+ "caseStatus": {
7778
+ "type": "string",
7779
+ "nullable": true,
7780
+ "description": "Airbnb's case-status label."
7781
+ },
7782
+ "statusText": {
7783
+ "type": "string",
7784
+ "nullable": true,
7785
+ "description": "Human-readable status detail."
7786
+ },
7787
+ "suggestedActionText": {
7788
+ "type": "string",
7789
+ "nullable": true,
7790
+ "description": "Airbnb's hint on whose turn it is to act next \u2014 track progress with it."
7791
+ },
7792
+ "customerSupportInitiated": {
7793
+ "type": "boolean",
7794
+ "nullable": true,
7795
+ "description": "True when Airbnb Customer Support (not the host/guest) opened the case."
7796
+ },
7797
+ "productType": {
7798
+ "type": "string",
7799
+ "nullable": true
7800
+ },
7801
+ "initiator": {
7802
+ "type": "object",
7803
+ "nullable": true,
7804
+ "description": "Who opened the case (id + name)."
7805
+ },
7806
+ "responder": {
7807
+ "type": "object",
7808
+ "nullable": true,
7809
+ "description": "Who responds (id + name)."
7810
+ },
7811
+ "createdAt": {
7812
+ "type": "string",
7813
+ "format": "date-time",
7814
+ "nullable": true
7815
+ },
7816
+ "updatedAt": {
7817
+ "type": "string",
7818
+ "format": "date-time",
7819
+ "nullable": true
7820
+ },
7821
+ "syncedAt": {
7822
+ "type": "string",
7823
+ "format": "date-time",
7824
+ "nullable": true,
7825
+ "description": "When Repull last refreshed this case from Airbnb."
7826
+ }
7827
+ }
7828
+ },
7435
7829
  "AirbnbConnectionHost": {
7436
7830
  "type": "object",
7437
7831
  "description": "One Airbnb host record under the workspace, decorated with its most recent disconnect reason from `airbnb_host_events` (backfill events excluded).",
@@ -37672,6 +38066,379 @@
37672
38066
  }
37673
38067
  }
37674
38068
  }
38069
+ },
38070
+ "/v1/transactions/{id}/statement": {
38071
+ "get": {
38072
+ "operationId": "get_transaction_statement",
38073
+ "summary": "Download the original payout statement",
38074
+ "description": "Downloads the channel's ORIGINAL payout statement \u2014 the authoritative settlement record a host reconciles against \u2014 for a payout transaction. `{id}` is the payout `transactionId` (e.g. `booking_payout_5463377687_bank_transfer`). Repull serves the stored bytes itself (no channel session), so unlike the channel's own link it never expires or leaks a session. PDF by default; pass `?format=csv` for the CSV remittance. Returns `404` when no statement was captured for the payout (e.g. an upcoming payout, or a channel that has none).",
38075
+ "tags": [
38076
+ "Transactions"
38077
+ ],
38078
+ "parameters": [
38079
+ {
38080
+ "$ref": "#/components/parameters/XSchemaHeader"
38081
+ },
38082
+ {
38083
+ "name": "id",
38084
+ "in": "path",
38085
+ "required": true,
38086
+ "description": "The payout transaction id (`transactionId`).",
38087
+ "schema": {
38088
+ "type": "string"
38089
+ }
38090
+ },
38091
+ {
38092
+ "name": "format",
38093
+ "in": "query",
38094
+ "required": false,
38095
+ "description": "Statement format.",
38096
+ "schema": {
38097
+ "type": "string",
38098
+ "enum": [
38099
+ "pdf",
38100
+ "csv"
38101
+ ],
38102
+ "default": "pdf"
38103
+ }
38104
+ }
38105
+ ],
38106
+ "responses": {
38107
+ "200": {
38108
+ "description": "The statement file (PDF by default, or CSV).",
38109
+ "content": {
38110
+ "application/pdf": {
38111
+ "schema": {
38112
+ "type": "string",
38113
+ "format": "binary"
38114
+ }
38115
+ },
38116
+ "text/csv": {
38117
+ "schema": {
38118
+ "type": "string"
38119
+ }
38120
+ }
38121
+ }
38122
+ },
38123
+ "400": {
38124
+ "$ref": "#/components/responses/BadRequest"
38125
+ },
38126
+ "401": {
38127
+ "$ref": "#/components/responses/Unauthorized"
38128
+ },
38129
+ "404": {
38130
+ "$ref": "#/components/responses/NotFound"
38131
+ },
38132
+ "500": {
38133
+ "$ref": "#/components/responses/InternalError"
38134
+ }
38135
+ }
38136
+ }
38137
+ },
38138
+ "/v1/channels/airbnb/resolutions": {
38139
+ "get": {
38140
+ "operationId": "list_airbnb_resolutions",
38141
+ "summary": "List Airbnb Resolution Center cases",
38142
+ "description": "The host's Airbnb Resolution Center cases (AirCover / damage, extra-guest, refund and change requests), open and closed. Served from the database; `POST` this path to refresh from Airbnb. READ-ONLY upstream \u2014 Airbnb's Resolutions API is read-only; a claim is created, evidence added and status changed only in Airbnb's Resolution Center UI, not via API. Use this for visibility and action tracking (`suggestedActionText`). The money a resolution moved is in the transactions ledger as `Resolution Payout` / `Resolution Adjustment` rows sharing the same reference \u2014 join on `resolutionId`. Cursor-paginated, newest first.",
38143
+ "tags": [
38144
+ "Resolutions"
38145
+ ],
38146
+ "parameters": [
38147
+ {
38148
+ "$ref": "#/components/parameters/XSchemaHeader"
38149
+ },
38150
+ {
38151
+ "name": "status",
38152
+ "in": "query",
38153
+ "required": false,
38154
+ "description": "Filter by lifecycle: `open` (still needs action) or `closed` (settled). Omit for all.",
38155
+ "schema": {
38156
+ "type": "string",
38157
+ "enum": [
38158
+ "open",
38159
+ "closed"
38160
+ ]
38161
+ }
38162
+ },
38163
+ {
38164
+ "name": "limit",
38165
+ "in": "query",
38166
+ "required": false,
38167
+ "description": "Page size (default 50, max 200).",
38168
+ "schema": {
38169
+ "type": "integer",
38170
+ "minimum": 1,
38171
+ "maximum": 200
38172
+ }
38173
+ },
38174
+ {
38175
+ "name": "cursor",
38176
+ "in": "query",
38177
+ "required": false,
38178
+ "description": "Opaque pagination cursor from a previous `pagination.nextCursor`.",
38179
+ "schema": {
38180
+ "type": "string"
38181
+ }
38182
+ }
38183
+ ],
38184
+ "responses": {
38185
+ "200": {
38186
+ "description": "Resolutions",
38187
+ "content": {
38188
+ "application/json": {
38189
+ "schema": {
38190
+ "type": "object",
38191
+ "required": [
38192
+ "data",
38193
+ "pagination"
38194
+ ],
38195
+ "properties": {
38196
+ "data": {
38197
+ "type": "array",
38198
+ "items": {
38199
+ "$ref": "#/components/schemas/Resolution"
38200
+ }
38201
+ },
38202
+ "pagination": {
38203
+ "$ref": "#/components/schemas/Pagination"
38204
+ }
38205
+ }
38206
+ }
38207
+ }
38208
+ }
38209
+ },
38210
+ "401": {
38211
+ "$ref": "#/components/responses/Unauthorized"
38212
+ },
38213
+ "422": {
38214
+ "$ref": "#/components/responses/UnprocessableEntity"
38215
+ },
38216
+ "500": {
38217
+ "$ref": "#/components/responses/InternalError"
38218
+ }
38219
+ }
38220
+ },
38221
+ "post": {
38222
+ "operationId": "refresh_airbnb_resolutions",
38223
+ "summary": "Refresh Airbnb resolutions from Airbnb",
38224
+ "description": "Pulls the latest Resolution Center cases from Airbnb (read-only) and stores them, then read with GET. Optionally scope to one `account_id` and/or `status`.",
38225
+ "tags": [
38226
+ "Resolutions"
38227
+ ],
38228
+ "parameters": [
38229
+ {
38230
+ "$ref": "#/components/parameters/XSchemaHeader"
38231
+ }
38232
+ ],
38233
+ "requestBody": {
38234
+ "required": false,
38235
+ "content": {
38236
+ "application/json": {
38237
+ "schema": {
38238
+ "type": "object",
38239
+ "properties": {
38240
+ "account_id": {
38241
+ "type": "string",
38242
+ "description": "Limit the refresh to one Airbnb host id. Omit for all connected accounts."
38243
+ },
38244
+ "status": {
38245
+ "type": "string",
38246
+ "enum": [
38247
+ "OPEN",
38248
+ "CLOSED"
38249
+ ],
38250
+ "description": "Limit the refresh to one lifecycle. Omit for all."
38251
+ }
38252
+ }
38253
+ }
38254
+ }
38255
+ }
38256
+ },
38257
+ "responses": {
38258
+ "200": {
38259
+ "description": "Refresh outcome.",
38260
+ "content": {
38261
+ "application/json": {
38262
+ "schema": {
38263
+ "type": "object",
38264
+ "required": [
38265
+ "synced",
38266
+ "count",
38267
+ "accounts"
38268
+ ],
38269
+ "properties": {
38270
+ "synced": {
38271
+ "type": "boolean"
38272
+ },
38273
+ "count": {
38274
+ "type": "integer",
38275
+ "description": "Resolutions upserted across all accounts."
38276
+ },
38277
+ "accounts": {
38278
+ "type": "array",
38279
+ "items": {
38280
+ "type": "object",
38281
+ "required": [
38282
+ "account_id",
38283
+ "count"
38284
+ ],
38285
+ "properties": {
38286
+ "account_id": {
38287
+ "type": "string"
38288
+ },
38289
+ "count": {
38290
+ "type": "integer"
38291
+ },
38292
+ "error": {
38293
+ "type": "object",
38294
+ "nullable": true,
38295
+ "properties": {
38296
+ "code": {
38297
+ "type": "string"
38298
+ },
38299
+ "message": {
38300
+ "type": "string"
38301
+ }
38302
+ }
38303
+ }
38304
+ }
38305
+ }
38306
+ }
38307
+ }
38308
+ }
38309
+ }
38310
+ }
38311
+ },
38312
+ "401": {
38313
+ "$ref": "#/components/responses/Unauthorized"
38314
+ },
38315
+ "404": {
38316
+ "$ref": "#/components/responses/NotFound"
38317
+ },
38318
+ "422": {
38319
+ "$ref": "#/components/responses/UnprocessableEntity"
38320
+ },
38321
+ "500": {
38322
+ "$ref": "#/components/responses/InternalError"
38323
+ }
38324
+ }
38325
+ }
38326
+ },
38327
+ "/v1/channels/airbnb/resolutions/{id}": {
38328
+ "get": {
38329
+ "operationId": "get_airbnb_resolution",
38330
+ "summary": "Get an Airbnb Resolution Center case",
38331
+ "description": "One Airbnb Resolution Center case. `{id}` is the Airbnb resolution id (the `resolutionId` from the list, also a transaction's `reference`). Read-only (see the list endpoint). The amounts moved are in the transactions ledger \u2014 join `resolutionId` to a transaction's `reference`. 404 when it isn't in this workspace (POST the list endpoint to refresh first).",
38332
+ "tags": [
38333
+ "Resolutions"
38334
+ ],
38335
+ "parameters": [
38336
+ {
38337
+ "$ref": "#/components/parameters/XSchemaHeader"
38338
+ },
38339
+ {
38340
+ "name": "id",
38341
+ "in": "path",
38342
+ "required": true,
38343
+ "description": "The Airbnb resolution id.",
38344
+ "schema": {
38345
+ "type": "string"
38346
+ }
38347
+ }
38348
+ ],
38349
+ "responses": {
38350
+ "200": {
38351
+ "description": "Resolution",
38352
+ "content": {
38353
+ "application/json": {
38354
+ "schema": {
38355
+ "$ref": "#/components/schemas/Resolution"
38356
+ }
38357
+ }
38358
+ }
38359
+ },
38360
+ "401": {
38361
+ "$ref": "#/components/responses/Unauthorized"
38362
+ },
38363
+ "404": {
38364
+ "$ref": "#/components/responses/NotFound"
38365
+ },
38366
+ "500": {
38367
+ "$ref": "#/components/responses/InternalError"
38368
+ }
38369
+ }
38370
+ }
38371
+ },
38372
+ "/v1/connections/{id}/imports": {
38373
+ "get": {
38374
+ "operationId": "listConnectionImports",
38375
+ "summary": "List a connection's imports",
38376
+ "description": "The import runs of one connected account, newest first: the first sync after connecting, a room or unit mapped later, a reconnect, a re-sync. Each run says where it stands (`running`, `completed`, `failed`), its stages and what it imported.\n\nTo know when an account's first sync is done, wait for the `account.import.completed` webhook, or poll this endpoint (or `GET /v1/connect`, whose connections carry their latest `import`) until the newest run is no longer `running`.\n\nAuth: a Repull API key, or a Connect session token (`sessionId`).",
38377
+ "tags": [
38378
+ "Connections"
38379
+ ],
38380
+ "parameters": [
38381
+ {
38382
+ "name": "id",
38383
+ "in": "path",
38384
+ "required": true,
38385
+ "schema": {
38386
+ "type": "string"
38387
+ },
38388
+ "description": "Connection handle `{provider}:{externalAccountId}`, e.g. `booking_extranet:36`, `vrbo:12`, `airbnb:1234567`, `hostaway:27434` \u2014 the `provider` and `externalAccountId` of a connection on `GET /v1/connect`, or the account of an `account.*` webhook."
38389
+ },
38390
+ {
38391
+ "name": "limit",
38392
+ "in": "query",
38393
+ "required": false,
38394
+ "schema": {
38395
+ "type": "integer",
38396
+ "minimum": 1,
38397
+ "maximum": 100,
38398
+ "default": 20
38399
+ },
38400
+ "description": "How many runs to return, newest first."
38401
+ },
38402
+ {
38403
+ "name": "sessionId",
38404
+ "in": "query",
38405
+ "required": false,
38406
+ "schema": {
38407
+ "type": "string"
38408
+ },
38409
+ "description": "The Connect session ID (capability token)."
38410
+ }
38411
+ ],
38412
+ "responses": {
38413
+ "200": {
38414
+ "description": "Imports, newest first. Empty when the account has none recorded.",
38415
+ "content": {
38416
+ "application/json": {
38417
+ "schema": {
38418
+ "type": "object",
38419
+ "properties": {
38420
+ "data": {
38421
+ "type": "array",
38422
+ "items": {
38423
+ "$ref": "#/components/schemas/AccountImport"
38424
+ }
38425
+ },
38426
+ "pagination": {
38427
+ "$ref": "#/components/schemas/Pagination"
38428
+ }
38429
+ }
38430
+ }
38431
+ }
38432
+ }
38433
+ },
38434
+ "400": {
38435
+ "$ref": "#/components/responses/BadRequest"
38436
+ },
38437
+ "401": {
38438
+ "$ref": "#/components/responses/Unauthorized"
38439
+ }
38440
+ }
38441
+ }
37675
38442
  }
37676
38443
  }
37677
38444
  }