@medalsocial/sdk 1.8.0 → 1.10.0

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.
@@ -732,6 +732,160 @@ paths:
732
732
  $ref: "#/components/schemas/ApiResponse_BookingScheduleDayArray"
733
733
  default:
734
734
  $ref: "#/components/responses/ApiError"
735
+ /api/v1/bookings/persons:
736
+ get:
737
+ tags: [Bookings]
738
+ operationId: listContactPersons
739
+ summary: List a contact's persons
740
+ description: >-
741
+ Persons a contact books for — a child, a pet, an employee. No login of
742
+ their own. Active-only unless `include_inactive` is set.
743
+ parameters:
744
+ - name: contact_id
745
+ in: query
746
+ required: true
747
+ schema:
748
+ type: string
749
+ - name: include_inactive
750
+ in: query
751
+ schema:
752
+ type: boolean
753
+ responses:
754
+ "200":
755
+ description: Contact persons.
756
+ content:
757
+ application/json:
758
+ schema:
759
+ $ref: "#/components/schemas/ApiResponse_ContactPersonArray"
760
+ default:
761
+ $ref: "#/components/responses/ApiError"
762
+ post:
763
+ tags: [Bookings]
764
+ operationId: createContactPerson
765
+ summary: Add a person under a contact
766
+ requestBody:
767
+ required: true
768
+ content:
769
+ application/json:
770
+ schema:
771
+ $ref: "#/components/schemas/CreateContactPersonInput"
772
+ responses:
773
+ "201":
774
+ description: Created person.
775
+ content:
776
+ application/json:
777
+ schema:
778
+ $ref: "#/components/schemas/ApiResponse_ContactPerson"
779
+ default:
780
+ $ref: "#/components/responses/ApiError"
781
+ /api/v1/bookings/relations:
782
+ get:
783
+ tags: [Bookings]
784
+ operationId: listContactRelations
785
+ summary: List a contact's relations
786
+ description: Directional relations a contact holds, split into outgoing and incoming.
787
+ parameters:
788
+ - name: contact_id
789
+ in: query
790
+ required: true
791
+ schema:
792
+ type: string
793
+ responses:
794
+ "200":
795
+ description: Outgoing and incoming relations.
796
+ content:
797
+ application/json:
798
+ schema:
799
+ $ref: "#/components/schemas/ApiResponse_ContactRelations"
800
+ default:
801
+ $ref: "#/components/responses/ApiError"
802
+ post:
803
+ tags: [Bookings]
804
+ operationId: createContactRelation
805
+ summary: Create a relation from one contact to another
806
+ requestBody:
807
+ required: true
808
+ content:
809
+ application/json:
810
+ schema:
811
+ $ref: "#/components/schemas/CreateContactRelationInput"
812
+ responses:
813
+ "201":
814
+ description: Created relation id.
815
+ content:
816
+ application/json:
817
+ schema:
818
+ $ref: "#/components/schemas/ApiResponse_CreateContactRelationResult"
819
+ default:
820
+ $ref: "#/components/responses/ApiError"
821
+ /api/v1/bookings/events:
822
+ get:
823
+ tags: [Bookings]
824
+ operationId: listBookingEvents
825
+ summary: List arrangementer in a date range
826
+ parameters:
827
+ - name: from
828
+ in: query
829
+ required: true
830
+ description: Start of the window, `yyyy-mm-dd`, inclusive.
831
+ schema:
832
+ type: string
833
+ format: date
834
+ - name: to
835
+ in: query
836
+ required: true
837
+ description: End of the window, `yyyy-mm-dd`, inclusive.
838
+ schema:
839
+ type: string
840
+ format: date
841
+ - name: status
842
+ in: query
843
+ schema:
844
+ $ref: "#/components/schemas/BookingEventStatus"
845
+ responses:
846
+ "200":
847
+ description: Arrangementer in the window.
848
+ content:
849
+ application/json:
850
+ schema:
851
+ $ref: "#/components/schemas/ApiResponse_BookingEventArray"
852
+ default:
853
+ $ref: "#/components/responses/ApiError"
854
+ post:
855
+ tags: [Bookings]
856
+ operationId: createBookingEvent
857
+ summary: Create an arrangement from a template
858
+ requestBody:
859
+ required: true
860
+ content:
861
+ application/json:
862
+ schema:
863
+ $ref: "#/components/schemas/CreateBookingEventInput"
864
+ responses:
865
+ "201":
866
+ description: Created arrangement.
867
+ content:
868
+ application/json:
869
+ schema:
870
+ $ref: "#/components/schemas/ApiResponse_BookingEvent"
871
+ default:
872
+ $ref: "#/components/responses/ApiError"
873
+ /api/v1/bookings/events/{id}:
874
+ parameters:
875
+ - $ref: "#/components/parameters/Id"
876
+ get:
877
+ tags: [Bookings]
878
+ operationId: getBookingEvent
879
+ summary: Get an arrangement
880
+ responses:
881
+ "200":
882
+ description: Arrangement.
883
+ content:
884
+ application/json:
885
+ schema:
886
+ $ref: "#/components/schemas/ApiResponse_BookingEvent"
887
+ default:
888
+ $ref: "#/components/responses/ApiError"
735
889
  /api/v1/bookings/{id}:
736
890
  parameters:
737
891
  - $ref: "#/components/parameters/Id"
@@ -834,6 +988,98 @@ paths:
834
988
  $ref: "#/components/schemas/ApiResponse_BookingActionResult"
835
989
  default:
836
990
  $ref: "#/components/responses/ApiError"
991
+ /api/v1/bookings/{id}/payment:
992
+ parameters:
993
+ - $ref: "#/components/parameters/Id"
994
+ post:
995
+ tags: [Bookings]
996
+ operationId: startBookingPayment
997
+ summary: Start a Vipps payment for a booking
998
+ description: >-
999
+ Reserves (or charges) the booking's amount and returns the wallet
1000
+ redirect URL. The customer must have accepted your terms before this
1001
+ call — `terms_accepted` must be literally `true`, and a body omitting
1002
+ it is a 400. One live payment per booking: a second while one is
1003
+ outstanding answers 409, as does a booking that is not payable or a
1004
+ refusal from Vipps. A `return_url` this workspace's own sites do not
1005
+ vouch for answers 422, not 400 — the URL parses, it is just not yours.
1006
+ 403 when the payments switch or the bookings module is off.
1007
+ requestBody:
1008
+ required: true
1009
+ content:
1010
+ application/json:
1011
+ schema:
1012
+ $ref: "#/components/schemas/StartBookingPaymentInput"
1013
+ responses:
1014
+ "200":
1015
+ description: >-
1016
+ The reference and the SHOW-ONCE redirect URL. The URL is never
1017
+ returned again — the payment behind it expires after ten minutes,
1018
+ so a cached one leads into a payment that no longer exists.
1019
+ content:
1020
+ application/json:
1021
+ schema:
1022
+ $ref: "#/components/schemas/ApiResponse_BookingPaymentStart"
1023
+ default:
1024
+ $ref: "#/components/responses/ApiError"
1025
+ get:
1026
+ tags: [Bookings]
1027
+ operationId: getBookingPayment
1028
+ summary: Read the newest payment attempt on a booking
1029
+ description: >-
1030
+ Returns the newest attempt only. A booking with no payment yet, an
1031
+ unknown booking id and another workspace's booking all answer 404
1032
+ alike, so this is not an existence oracle.
1033
+ responses:
1034
+ "200":
1035
+ description: The payment. `redirect_url` is deliberately absent here.
1036
+ content:
1037
+ application/json:
1038
+ schema:
1039
+ $ref: "#/components/schemas/ApiResponse_BookingPayment"
1040
+ default:
1041
+ $ref: "#/components/responses/ApiError"
1042
+ /api/v1/bookings/manage/{token}/payment:
1043
+ parameters:
1044
+ - $ref: "#/components/parameters/ManageToken"
1045
+ post:
1046
+ tags: [Bookings]
1047
+ operationId: startManageBookingPayment
1048
+ summary: Start a payment on the customer's behalf
1049
+ description: >-
1050
+ The manage-token twin of `startBookingPayment` — same body, same
1051
+ responses; only the credential that authorizes it differs.
1052
+ requestBody:
1053
+ required: true
1054
+ content:
1055
+ application/json:
1056
+ schema:
1057
+ $ref: "#/components/schemas/StartBookingPaymentInput"
1058
+ responses:
1059
+ "200":
1060
+ description: The reference and the show-once redirect URL.
1061
+ content:
1062
+ application/json:
1063
+ schema:
1064
+ $ref: "#/components/schemas/ApiResponse_BookingPaymentStart"
1065
+ default:
1066
+ $ref: "#/components/responses/ApiError"
1067
+ get:
1068
+ tags: [Bookings]
1069
+ operationId: getManageBookingPayment
1070
+ summary: Read the payment on the customer's own booking
1071
+ description: >-
1072
+ An unknown token, another workspace's token and a booking with no
1073
+ payment yet all answer 404 alike.
1074
+ responses:
1075
+ "200":
1076
+ description: The payment. `redirect_url` is deliberately absent here.
1077
+ content:
1078
+ application/json:
1079
+ schema:
1080
+ $ref: "#/components/schemas/ApiResponse_BookingPayment"
1081
+ default:
1082
+ $ref: "#/components/responses/ApiError"
837
1083
  /api/v1/bookings/manage/{token}:
838
1084
  parameters:
839
1085
  - $ref: "#/components/parameters/ManageToken"
@@ -1051,9 +1297,13 @@ paths:
1051
1297
  summary: Export everything held about the signed-in contact
1052
1298
  description: >-
1053
1299
  A synchronous GDPR Art. 15 export of the contact's profile, family,
1054
- consents and bookings, as one JSON document. Read-only, so not
1055
- idempotency-keyed. Errors: `401 PORTAL_SESSION_REQUIRED`,
1056
- `401 PORTAL_SESSION_INVALID`, `403 FORBIDDEN`, `429 RATE_LIMITED`.
1300
+ consents and bookings, as one JSON document. Unlike `GET
1301
+ /api/v1/portal/me`, `contact.persons` here includes inactive persons
1302
+ so the export is a complete dump. `relations` lists every relation
1303
+ the contact is a party to, exposing only the counterpart's display
1304
+ name. Read-only, so not idempotency-keyed. Errors: `401
1305
+ PORTAL_SESSION_REQUIRED`, `401 PORTAL_SESSION_INVALID`, `403
1306
+ FORBIDDEN`, `429 RATE_LIMITED`.
1057
1307
  responses:
1058
1308
  "200":
1059
1309
  description: The export.
@@ -2627,6 +2877,19 @@ components:
2627
2877
  BookingPaymentStatus:
2628
2878
  type: string
2629
2879
  enum: [none, reserved, captured, refunded]
2880
+ BookingPaymentMode:
2881
+ description: >-
2882
+ What a booking must have paid before the business honours it: nothing,
2883
+ a reservation captured later, or the full amount up front.
2884
+ type: string
2885
+ enum: [none, reserve, prepay]
2886
+ BookingPaymentState:
2887
+ description: >-
2888
+ The state of one payment attempt, in Medal's vocabulary rather than the
2889
+ wallet's — a Vipps payment stays AUTHORIZED after a capture, so read
2890
+ the øre aggregates to learn what actually moved.
2891
+ type: string
2892
+ enum: [created, authorized, captured, cancelled, refunded, failed, expired]
2630
2893
  BookingCreatedVia:
2631
2894
  type: string
2632
2895
  enum: [web, dashboard, walk_in, api]
@@ -2644,12 +2907,16 @@ components:
2644
2907
  - end_ts
2645
2908
  - booked_for_name
2646
2909
  - booked_for_birth_year
2910
+ - booked_for_person_id
2911
+ - event_id
2912
+ - event_order
2647
2913
  - party_sequence_id
2648
2914
  - status
2649
2915
  - cancelled_by
2650
2916
  - cancel_reason
2651
2917
  - rescheduled_from_id
2652
2918
  - payment_status
2919
+ - payment_mode
2653
2920
  - amount_ore
2654
2921
  - notes
2655
2922
  - internal_notes
@@ -2676,6 +2943,15 @@ components:
2676
2943
  booked_for_birth_year:
2677
2944
  description: A birth year, not a birthdate — the age bracket is all that is stored.
2678
2945
  type: [integer, "null"]
2946
+ booked_for_person_id:
2947
+ description: The ContactPerson this booking was made for, if any.
2948
+ type: [string, "null"]
2949
+ event_id:
2950
+ description: The BookingEvent this booking is a registration for, if any.
2951
+ type: [string, "null"]
2952
+ event_order:
2953
+ description: Position of this booking within its event's registrations, if any.
2954
+ type: [integer, "null"]
2679
2955
  party_sequence_id:
2680
2956
  description: Shared by every booking created in the same party request.
2681
2957
  type: [string, "null"]
@@ -2692,6 +2968,12 @@ components:
2692
2968
  type: [string, "null"]
2693
2969
  payment_status:
2694
2970
  $ref: "#/components/schemas/BookingPaymentStatus"
2971
+ payment_mode:
2972
+ description: >-
2973
+ What this booking required when it was made — frozen at creation.
2974
+ `payment_status: none` cannot tell "owes nothing" from "has not
2975
+ paid yet"; this can.
2976
+ $ref: "#/components/schemas/BookingPaymentMode"
2695
2977
  amount_ore:
2696
2978
  description: Price in integer øre. Never a float and never kroner.
2697
2979
  type: [integer, "null"]
@@ -2725,6 +3007,7 @@ components:
2725
3007
  - weekend_surcharge_pct
2726
3008
  - resource_requirements
2727
3009
  - bookable_online
3010
+ - payment
2728
3011
  - max_per_booking
2729
3012
  - color
2730
3013
  - sort_order
@@ -2758,6 +3041,13 @@ components:
2758
3041
  type: string
2759
3042
  bookable_online:
2760
3043
  type: boolean
3044
+ payment:
3045
+ description: >-
3046
+ Per-service payment requirement. `null` means no override — the
3047
+ workspace rule decides.
3048
+ oneOf:
3049
+ - $ref: "#/components/schemas/BookingPaymentMode"
3050
+ - type: "null"
2761
3051
  max_per_booking:
2762
3052
  type: [integer, "null"]
2763
3053
  color:
@@ -2880,6 +3170,9 @@ components:
2880
3170
  type: integer
2881
3171
  minimum: 1900
2882
3172
  maximum: 2200
3173
+ booked_for_person_id:
3174
+ description: Book this line on behalf of a ContactPerson rather than the contact.
3175
+ type: string
2883
3176
  CreateBookingInput:
2884
3177
  type: object
2885
3178
  required: [items, contact]
@@ -2975,6 +3268,7 @@ components:
2975
3268
  - party_sequence_id
2976
3269
  - amount_ore
2977
3270
  - payment_status
3271
+ - payment_mode
2978
3272
  - time_zone
2979
3273
  - cancel_window_hours
2980
3274
  - reschedule_window_hours
@@ -3022,6 +3316,11 @@ components:
3022
3316
  oneOf:
3023
3317
  - $ref: "#/components/schemas/BookingPaymentStatus"
3024
3318
  - type: "null"
3319
+ payment_mode:
3320
+ description: >-
3321
+ What this booking requires — what a manage page checks before
3322
+ offering «Betal nå».
3323
+ $ref: "#/components/schemas/BookingPaymentMode"
3025
3324
  time_zone:
3026
3325
  description: IANA zone the booking's local times should be rendered in.
3027
3326
  type: [string, "null"]
@@ -3086,6 +3385,131 @@ components:
3086
3385
  $ref: "#/components/schemas/BookingTimestampInput"
3087
3386
  new_resource_id:
3088
3387
  type: string
3388
+ StartBookingPaymentInput:
3389
+ description: >-
3390
+ Body for `startBookingPayment` and `startManageBookingPayment`.
3391
+ type: object
3392
+ required: [return_url, terms_accepted]
3393
+ properties:
3394
+ return_url:
3395
+ description: >-
3396
+ Where the wallet returns the customer. Must be a URL one of this
3397
+ workspace's own sites vouches for; anything else answers 422.
3398
+ type: string
3399
+ minLength: 1
3400
+ maxLength: 2048
3401
+ terms_accepted:
3402
+ description: >-
3403
+ Must be literally `true`. The customer has to actively accept the
3404
+ merchant's terms BEFORE a payment is initiated, so omitting it or
3405
+ sending `false` is a 400 and leaves no payment behind.
3406
+ const: true
3407
+ type: boolean
3408
+ terms_version:
3409
+ description: The caller's own version label for the terms that were accepted.
3410
+ type: string
3411
+ minLength: 1
3412
+ maxLength: 64
3413
+ terms_text:
3414
+ description: The exact text that was accepted, stored with the consent record.
3415
+ type: string
3416
+ maxLength: 2000
3417
+ BookingPaymentStart:
3418
+ description: >-
3419
+ The result of starting a payment. `redirect_url` is handed over here
3420
+ and nowhere else.
3421
+ type: object
3422
+ required: [reference, redirect_url, state]
3423
+ properties:
3424
+ reference:
3425
+ description: The wallet reference for this attempt.
3426
+ type: string
3427
+ redirect_url:
3428
+ description: >-
3429
+ Send the customer here UNCHANGED — hand it to the Vipps Widget SDK.
3430
+ SHOW-ONCE: it is not returned by `getBookingPayment`, and the
3431
+ payment behind it expires after ten minutes.
3432
+ type: string
3433
+ state:
3434
+ $ref: "#/components/schemas/BookingPaymentState"
3435
+ BookingPayment:
3436
+ description: >-
3437
+ One payment attempt on a booking. Money is integer øre, and the four
3438
+ aggregates are numbers rather than nulls — "nothing captured" is `0`.
3439
+ `redirect_url`, the wallet's own refusal text and the trace id are
3440
+ deliberately absent.
3441
+ type: object
3442
+ required:
3443
+ - reference
3444
+ - provider
3445
+ - state
3446
+ - mode
3447
+ - attempt
3448
+ - amount_ore
3449
+ - authorized_ore
3450
+ - captured_ore
3451
+ - refunded_ore
3452
+ - cancelled_ore
3453
+ - currency
3454
+ - capture_guaranteed_until
3455
+ - terms_version
3456
+ - terms_accepted_at
3457
+ - failure_code
3458
+ - created_at
3459
+ - updated_at
3460
+ properties:
3461
+ reference:
3462
+ type: string
3463
+ provider:
3464
+ const: vipps
3465
+ type: string
3466
+ state:
3467
+ $ref: "#/components/schemas/BookingPaymentState"
3468
+ mode:
3469
+ description: Never `none` — a payment exists only where one was required.
3470
+ type: string
3471
+ enum: [reserve, prepay]
3472
+ attempt:
3473
+ description: 1 for the first attempt on this booking, incrementing per retry.
3474
+ type: integer
3475
+ amount_ore:
3476
+ description: The amount this attempt is for, in integer øre.
3477
+ type: integer
3478
+ authorized_ore:
3479
+ type: integer
3480
+ captured_ore:
3481
+ type: integer
3482
+ refunded_ore:
3483
+ type: integer
3484
+ cancelled_ore:
3485
+ type: integer
3486
+ currency:
3487
+ const: NOK
3488
+ type: string
3489
+ capture_guaranteed_until:
3490
+ description: >-
3491
+ The last moment a capture is GUARANTEED to succeed. The card behind
3492
+ the wallet may release the reservation afterwards, so a capture
3493
+ past it can fail even though the payment still looks authorized.
3494
+ Null until the customer has approved.
3495
+ type: [string, "null"]
3496
+ format: date-time
3497
+ terms_version:
3498
+ type: [string, "null"]
3499
+ terms_accepted_at:
3500
+ type: [string, "null"]
3501
+ format: date-time
3502
+ failure_code:
3503
+ description: >-
3504
+ The wallet's numeric error code from the last failed operation —
3505
+ what a caller branches on.
3506
+ type: [string, "null"]
3507
+ created_at:
3508
+ type: [string, "null"]
3509
+ format: date-time
3510
+ updated_at:
3511
+ type: [string, "null"]
3512
+ format: date-time
3089
3513
  BookingsPagination:
3090
3514
  description: >-
3091
3515
  Pagination for a bookings page. `truncated` is the extra statement:
@@ -3808,6 +4232,10 @@ components:
3808
4232
  $ref: "#/components/schemas/Envelope_BookingActionResult"
3809
4233
  ApiResponse_BookingRescheduleResult:
3810
4234
  $ref: "#/components/schemas/Envelope_BookingRescheduleResult"
4235
+ ApiResponse_BookingPaymentStart:
4236
+ $ref: "#/components/schemas/Envelope_BookingPaymentStart"
4237
+ ApiResponse_BookingPayment:
4238
+ $ref: "#/components/schemas/Envelope_BookingPayment"
3811
4239
  ApiResponse_ManageSummary:
3812
4240
  $ref: "#/components/schemas/Envelope_ManageSummary"
3813
4241
  ApiResponse_PortalLoginStartResult:
@@ -4145,6 +4573,18 @@ components:
4145
4573
  properties:
4146
4574
  data:
4147
4575
  $ref: "#/components/schemas/BookingRescheduleResult"
4576
+ Envelope_BookingPaymentStart:
4577
+ type: object
4578
+ required: [data]
4579
+ properties:
4580
+ data:
4581
+ $ref: "#/components/schemas/BookingPaymentStart"
4582
+ Envelope_BookingPayment:
4583
+ type: object
4584
+ required: [data]
4585
+ properties:
4586
+ data:
4587
+ $ref: "#/components/schemas/BookingPayment"
4148
4588
  Envelope_ManageSummary:
4149
4589
  type: object
4150
4590
  required: [data]
@@ -4213,6 +4653,41 @@ components:
4213
4653
  type: string
4214
4654
  birth_year:
4215
4655
  type: integer
4656
+ PortalPerson:
4657
+ description: >-
4658
+ A person the contact books for — a child, a pet — with no login of
4659
+ its own.
4660
+ type: object
4661
+ required:
4662
+ [person_id, name, birth_year, relation_type, relation_label, notes, active]
4663
+ properties:
4664
+ person_id:
4665
+ type: string
4666
+ name:
4667
+ type: string
4668
+ birth_year:
4669
+ type: [integer, "null"]
4670
+ relation_type:
4671
+ $ref: "#/components/schemas/RelationType"
4672
+ relation_label:
4673
+ type: [string, "null"]
4674
+ notes:
4675
+ type: [string, "null"]
4676
+ active:
4677
+ type: boolean
4678
+ description: >-
4679
+ False for a person the customer removed or that was promoted to
4680
+ its own contact; `me` returns active persons only, the export
4681
+ returns all.
4682
+ PortalLabels:
4683
+ description: The workspace's own words for the person concept, e.g. `"Barn"`.
4684
+ type: object
4685
+ required: [person, persons]
4686
+ properties:
4687
+ person:
4688
+ type: string
4689
+ persons:
4690
+ type: string
4216
4691
  PortalProfile:
4217
4692
  type: object
4218
4693
  required:
@@ -4222,6 +4697,8 @@ components:
4222
4697
  - last_name
4223
4698
  - phone
4224
4699
  - family
4700
+ - persons
4701
+ - labels
4225
4702
  - marketing_consent
4226
4703
  - created_at
4227
4704
  properties:
@@ -4239,6 +4716,12 @@ components:
4239
4716
  type: array
4240
4717
  items:
4241
4718
  $ref: "#/components/schemas/PortalFamilyMember"
4719
+ persons:
4720
+ type: array
4721
+ items:
4722
+ $ref: "#/components/schemas/PortalPerson"
4723
+ labels:
4724
+ $ref: "#/components/schemas/PortalLabels"
4242
4725
  marketing_consent:
4243
4726
  type: boolean
4244
4727
  created_at:
@@ -4340,10 +4823,35 @@ components:
4340
4823
  description: Unix timestamp in milliseconds, or `null`.
4341
4824
  source:
4342
4825
  type: string
4826
+ PortalExportRelation:
4827
+ description: A relation the exporting contact is a party to; only the counterpart's display name is exposed.
4828
+ type: object
4829
+ required:
4830
+ - direction
4831
+ - type
4832
+ - custom_label
4833
+ - since
4834
+ - note
4835
+ - counterpart_name
4836
+ properties:
4837
+ direction:
4838
+ type: string
4839
+ enum: [outgoing, incoming]
4840
+ type:
4841
+ $ref: "#/components/schemas/RelationType"
4842
+ custom_label:
4843
+ type: [string, "null"]
4844
+ since:
4845
+ type: [integer, "null"]
4846
+ description: Unix timestamp in milliseconds.
4847
+ note:
4848
+ type: [string, "null"]
4849
+ counterpart_name:
4850
+ type: string
4343
4851
  PortalExport:
4344
4852
  description: Everything the workspace holds about the signed-in contact (GDPR Art. 15).
4345
4853
  type: object
4346
- required: [exported_at, contact, family, consents, bookings]
4854
+ required: [exported_at, contact, family, consents, bookings, relations]
4347
4855
  properties:
4348
4856
  exported_at:
4349
4857
  type: integer
@@ -4362,6 +4870,10 @@ components:
4362
4870
  type: array
4363
4871
  items:
4364
4872
  $ref: "#/components/schemas/PortalBooking"
4873
+ relations:
4874
+ type: array
4875
+ items:
4876
+ $ref: "#/components/schemas/PortalExportRelation"
4365
4877
  Envelope_PortalLoginStartResult:
4366
4878
  type: object
4367
4879
  required: [data]
@@ -4743,3 +5255,293 @@ components:
4743
5255
  properties:
4744
5256
  data:
4745
5257
  $ref: "#/components/schemas/ChannelConnectionDisconnectResult"
5258
+ RelationType:
5259
+ description: How a person or a relation relates to a contact.
5260
+ type: string
5261
+ enum: [guardian, owner, employer, caregiver, partner, custom]
5262
+ ContactPerson:
5263
+ description: >-
5264
+ A person a contact books for — a child, a pet, an employee. No login
5265
+ of their own.
5266
+ type: object
5267
+ required:
5268
+ - person_id
5269
+ - contact_id
5270
+ - name
5271
+ - birth_year
5272
+ - relation_type
5273
+ - relation_label
5274
+ - notes
5275
+ - active
5276
+ - promoted_to_contact_id
5277
+ - created_at
5278
+ - updated_at
5279
+ properties:
5280
+ person_id:
5281
+ type: string
5282
+ contact_id:
5283
+ type: string
5284
+ name:
5285
+ type: string
5286
+ birth_year:
5287
+ type: [integer, "null"]
5288
+ relation_type:
5289
+ $ref: "#/components/schemas/RelationType"
5290
+ relation_label:
5291
+ type: [string, "null"]
5292
+ notes:
5293
+ type: [string, "null"]
5294
+ active:
5295
+ type: boolean
5296
+ promoted_to_contact_id:
5297
+ type: [string, "null"]
5298
+ created_at:
5299
+ type: string
5300
+ format: date-time
5301
+ updated_at:
5302
+ type: string
5303
+ format: date-time
5304
+ CreateContactPersonInput:
5305
+ type: object
5306
+ required: [contact_id, name, relation_type]
5307
+ properties:
5308
+ contact_id:
5309
+ type: string
5310
+ name:
5311
+ type: string
5312
+ birth_year:
5313
+ type: integer
5314
+ relation_type:
5315
+ $ref: "#/components/schemas/RelationType"
5316
+ relation_label:
5317
+ type: string
5318
+ notes:
5319
+ type: string
5320
+ ContactRelation:
5321
+ description: One directional relation between two contacts.
5322
+ type: object
5323
+ required:
5324
+ - relation_id
5325
+ - from_contact_id
5326
+ - to_contact_id
5327
+ - type
5328
+ - custom_label
5329
+ - since
5330
+ - note
5331
+ - counterpart_name
5332
+ - created_at
5333
+ properties:
5334
+ relation_id:
5335
+ type: string
5336
+ from_contact_id:
5337
+ type: string
5338
+ to_contact_id:
5339
+ type: string
5340
+ type:
5341
+ $ref: "#/components/schemas/RelationType"
5342
+ custom_label:
5343
+ type: [string, "null"]
5344
+ since:
5345
+ type: [integer, "null"]
5346
+ description: Unix timestamp in milliseconds.
5347
+ note:
5348
+ type: [string, "null"]
5349
+ counterpart_name:
5350
+ type: string
5351
+ description: Empty string when the counterpart contact no longer exists.
5352
+ created_at:
5353
+ type: string
5354
+ format: date-time
5355
+ ContactRelations:
5356
+ description: Relations a contact holds, split by direction.
5357
+ type: object
5358
+ required: [outgoing, incoming]
5359
+ properties:
5360
+ outgoing:
5361
+ type: array
5362
+ items:
5363
+ $ref: "#/components/schemas/ContactRelation"
5364
+ incoming:
5365
+ type: array
5366
+ items:
5367
+ $ref: "#/components/schemas/ContactRelation"
5368
+ CreateContactRelationInput:
5369
+ type: object
5370
+ required: [from_contact_id, to_contact_id, type]
5371
+ properties:
5372
+ from_contact_id:
5373
+ type: string
5374
+ to_contact_id:
5375
+ type: string
5376
+ type:
5377
+ $ref: "#/components/schemas/RelationType"
5378
+ custom_label:
5379
+ type: string
5380
+ since:
5381
+ type: integer
5382
+ description: Unix timestamp in milliseconds.
5383
+ note:
5384
+ type: string
5385
+ CreateContactRelationResult:
5386
+ type: object
5387
+ required: [relation_id]
5388
+ properties:
5389
+ relation_id:
5390
+ type: string
5391
+ BookingEventStatus:
5392
+ type: string
5393
+ enum: [draft, open, closed, completed, cancelled]
5394
+ BookingEventTemplateKey:
5395
+ type: string
5396
+ enum: [kindergarten_visit, company_day, class, open_day, custom]
5397
+ BookingEvent:
5398
+ description: An arrangement — a scheduled group session bookings register against.
5399
+ type: object
5400
+ required:
5401
+ - event_id
5402
+ - template_id
5403
+ - host_id
5404
+ - date
5405
+ - window_start_minute
5406
+ - window_end_minute
5407
+ - place
5408
+ - capacity
5409
+ - minimum
5410
+ - registered_count
5411
+ - service_ids
5412
+ - resource_ids
5413
+ - price_override_ore
5414
+ - status
5415
+ - registration_closes_at
5416
+ - slug
5417
+ - created_at
5418
+ - updated_at
5419
+ properties:
5420
+ event_id:
5421
+ type: string
5422
+ template_id:
5423
+ type: string
5424
+ host_id:
5425
+ type: [string, "null"]
5426
+ date:
5427
+ description: yyyy-mm-dd in the workspace time zone.
5428
+ type: string
5429
+ format: date
5430
+ window_start_minute:
5431
+ type: integer
5432
+ window_end_minute:
5433
+ type: integer
5434
+ place:
5435
+ type: string
5436
+ enum: [at_host, in_house]
5437
+ capacity:
5438
+ type: integer
5439
+ minimum:
5440
+ type: integer
5441
+ registered_count:
5442
+ type: integer
5443
+ service_ids:
5444
+ type: array
5445
+ items:
5446
+ type: string
5447
+ resource_ids:
5448
+ type: array
5449
+ items:
5450
+ type: string
5451
+ price_override_ore:
5452
+ type: [integer, "null"]
5453
+ status:
5454
+ $ref: "#/components/schemas/BookingEventStatus"
5455
+ registration_closes_at:
5456
+ type: string
5457
+ format: date-time
5458
+ slug:
5459
+ type: string
5460
+ created_at:
5461
+ type: string
5462
+ format: date-time
5463
+ updated_at:
5464
+ type: string
5465
+ format: date-time
5466
+ CreateBookingEventInput:
5467
+ type: object
5468
+ required: [template_key, date, window_start_minute, place, service_ids, resource_ids]
5469
+ properties:
5470
+ template_key:
5471
+ $ref: "#/components/schemas/BookingEventTemplateKey"
5472
+ host_id:
5473
+ type: string
5474
+ date:
5475
+ type: string
5476
+ format: date
5477
+ window_start_minute:
5478
+ type: integer
5479
+ window_end_minute:
5480
+ type: integer
5481
+ place:
5482
+ type: string
5483
+ enum: [at_host, in_house]
5484
+ capacity:
5485
+ type: integer
5486
+ minimum:
5487
+ type: integer
5488
+ service_ids:
5489
+ type: array
5490
+ items:
5491
+ type: string
5492
+ resource_ids:
5493
+ type: array
5494
+ items:
5495
+ type: string
5496
+ ApiResponse_ContactPersonArray:
5497
+ $ref: "#/components/schemas/Envelope_ContactPersonArray"
5498
+ ApiResponse_ContactPerson:
5499
+ $ref: "#/components/schemas/Envelope_ContactPerson"
5500
+ ApiResponse_ContactRelations:
5501
+ $ref: "#/components/schemas/Envelope_ContactRelations"
5502
+ ApiResponse_CreateContactRelationResult:
5503
+ $ref: "#/components/schemas/Envelope_CreateContactRelationResult"
5504
+ ApiResponse_BookingEventArray:
5505
+ $ref: "#/components/schemas/Envelope_BookingEventArray"
5506
+ ApiResponse_BookingEvent:
5507
+ $ref: "#/components/schemas/Envelope_BookingEvent"
5508
+ Envelope_ContactPersonArray:
5509
+ type: object
5510
+ required: [data]
5511
+ properties:
5512
+ data:
5513
+ type: array
5514
+ items:
5515
+ $ref: "#/components/schemas/ContactPerson"
5516
+ Envelope_ContactPerson:
5517
+ type: object
5518
+ required: [data]
5519
+ properties:
5520
+ data:
5521
+ $ref: "#/components/schemas/ContactPerson"
5522
+ Envelope_ContactRelations:
5523
+ type: object
5524
+ required: [data]
5525
+ properties:
5526
+ data:
5527
+ $ref: "#/components/schemas/ContactRelations"
5528
+ Envelope_CreateContactRelationResult:
5529
+ type: object
5530
+ required: [data]
5531
+ properties:
5532
+ data:
5533
+ $ref: "#/components/schemas/CreateContactRelationResult"
5534
+ Envelope_BookingEventArray:
5535
+ type: object
5536
+ required: [data]
5537
+ properties:
5538
+ data:
5539
+ type: array
5540
+ items:
5541
+ $ref: "#/components/schemas/BookingEvent"
5542
+ Envelope_BookingEvent:
5543
+ type: object
5544
+ required: [data]
5545
+ properties:
5546
+ data:
5547
+ $ref: "#/components/schemas/BookingEvent"