@payware/mcp-server 1.4.0 → 1.5.1
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.
- package/package.json +1 -1
- package/src/isv/transactions/create-transaction.js +19 -7
- package/src/isv/transactions/process-transaction.js +12 -2
- package/src/merchant/transactions/cancel-transaction.js +1 -1
- package/src/merchant/transactions/create-transaction.js +14 -2
- package/src/merchant/transactions/process-transaction.js +12 -2
- package/src/payment-institution/transactions/create-pi-transaction.js +11 -1
- package/src/payment-institution/transactions/finalize-transaction.js +1 -1
- package/src/payment-institution/transactions/process-pi-transaction.js +12 -2
package/package.json
CHANGED
|
@@ -37,6 +37,7 @@ export async function createTransaction({
|
|
|
37
37
|
barBarHeight,
|
|
38
38
|
barFontSize,
|
|
39
39
|
barHumanReadableLocation,
|
|
40
|
+
idempotencyKey,
|
|
40
41
|
useSandbox = true
|
|
41
42
|
}) {
|
|
42
43
|
// ISV-specific validation
|
|
@@ -132,13 +133,17 @@ export async function createTransaction({
|
|
|
132
133
|
headers: {
|
|
133
134
|
'Authorization': `Bearer ${jwtData.token}`,
|
|
134
135
|
'Content-Type': 'application/json',
|
|
135
|
-
'Api-Version': '1'
|
|
136
|
+
'Api-Version': '1',
|
|
137
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
136
138
|
},
|
|
137
139
|
// Tell axios to send the string as-is, don't serialize it again
|
|
138
140
|
transformRequest: [(data) => data]
|
|
139
141
|
});
|
|
140
142
|
|
|
141
|
-
|
|
143
|
+
// A retry answered from the first call (Idempotency-Key) says so in a header, not in the body.
|
|
144
|
+
return response.headers?.['idempotent-replayed'] === 'true'
|
|
145
|
+
? { ...response.data, replayed: true }
|
|
146
|
+
: response.data;
|
|
142
147
|
} catch (error) {
|
|
143
148
|
throw describeApiError(error, 'call the payware API');
|
|
144
149
|
}
|
|
@@ -166,11 +171,13 @@ now returns 403, check the merchant's plan first.
|
|
|
166
171
|
answers **403 ERR_SHOP_NOT_IN_SCOPE**, and \`payware_shops_list\` returns only the in-scope ones.
|
|
167
172
|
Omitting \`shop\` uses the merchant's default shop, which may itself be out of scope.
|
|
168
173
|
|
|
169
|
-
ℹ️ **Producer attribution does not apply here.**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
ℹ️ **Producer attribution does not apply here.** Whoever made the API call owns the sale, so an ISV
|
|
175
|
+
call is an ISV sale even when the ISV's software is running on a hardware producer's terminal, and the
|
|
176
|
+
producer earns nothing from it. This tool therefore does not send \`producerPartnerId\` /
|
|
177
|
+
\`terminalId\` / \`terminalManufacturer\`. The server does accept them on an ISV call - it checks
|
|
178
|
+
them (an unrecognised producer is a 400) and records them for provenance - but they never move the
|
|
179
|
+
sale to the producer. Use \`payware_operations_create_transaction\` from the merchant role if the
|
|
180
|
+
terminal producer is meant to be attributed.
|
|
174
181
|
|
|
175
182
|
**Transaction Types:**
|
|
176
183
|
- PLAIN: Basic transaction without visual codes
|
|
@@ -200,6 +207,11 @@ merchant role if the terminal producer is meant to be attributed.
|
|
|
200
207
|
type: 'object',
|
|
201
208
|
required: ['merchantPartnerId', 'oauth2Token', 'reasonL1'],
|
|
202
209
|
properties: {
|
|
210
|
+
idempotencyKey: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
213
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
214
|
+
},
|
|
203
215
|
// ISV Authentication
|
|
204
216
|
merchantPartnerId: {
|
|
205
217
|
type: 'string',
|
|
@@ -40,6 +40,7 @@ export async function processTransaction({
|
|
|
40
40
|
paymentMethod,
|
|
41
41
|
merchantPartnerId,
|
|
42
42
|
oauth2Token,
|
|
43
|
+
idempotencyKey,
|
|
43
44
|
useSandbox = true
|
|
44
45
|
}) {
|
|
45
46
|
if (!transactionId) {
|
|
@@ -109,13 +110,17 @@ export async function processTransaction({
|
|
|
109
110
|
headers: {
|
|
110
111
|
'Authorization': `Bearer ${jwtData.token}`,
|
|
111
112
|
'Content-Type': 'application/json',
|
|
112
|
-
'Api-Version': '1'
|
|
113
|
+
'Api-Version': '1',
|
|
114
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
113
115
|
},
|
|
114
116
|
// Tell axios to send the string as-is, don't serialize it again
|
|
115
117
|
transformRequest: [(data) => data]
|
|
116
118
|
});
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
// A retry answered from the first call (Idempotency-Key) says so in a header, not in the body.
|
|
121
|
+
return response.headers?.['idempotent-replayed'] === 'true'
|
|
122
|
+
? { ...response.data, replayed: true }
|
|
123
|
+
: response.data;
|
|
119
124
|
} catch (error) {
|
|
120
125
|
throw describeApiError(error, 'call the payware API');
|
|
121
126
|
}
|
|
@@ -148,6 +153,11 @@ payware returns on the response is the value to echo back at finalize, unchanged
|
|
|
148
153
|
type: 'object',
|
|
149
154
|
required: ['transactionId', 'amount', 'currency', 'reasonL1', 'merchantPartnerId', 'oauth2Token'],
|
|
150
155
|
properties: {
|
|
156
|
+
idempotencyKey: {
|
|
157
|
+
type: "string",
|
|
158
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
159
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
160
|
+
},
|
|
151
161
|
transactionId: {
|
|
152
162
|
type: 'string',
|
|
153
163
|
description: "The customer's transaction to process, e.g. \"pw7e4rCToG\""
|
|
@@ -214,7 +214,7 @@ ${JSON.stringify(result.error.details || result.error, null, 2)}
|
|
|
214
214
|
**Timestamp:** ${result.timestamp}
|
|
215
215
|
|
|
216
216
|
**Common Issues:**
|
|
217
|
-
1. **ERR_MISSING_TRANSACTION**: Transaction not found
|
|
217
|
+
1. **ERR_MISSING_TRANSACTION**: Transaction not found. **ERR_TRANSACTION_EXPIRED** (also 404): its time to live has run out and it is already closed as unpaid
|
|
218
218
|
2. **ERR_ALREADY_PROCESSED**: Transaction already processed, cannot cancel
|
|
219
219
|
3. **ERR_UNAUTHORIZED_OPERATION**: Only transaction creator can cancel
|
|
220
220
|
4. **ERR_INVALID_STATUS_MESSAGE**: Status message invalid or too long
|
|
@@ -40,6 +40,7 @@ export async function createTransaction({
|
|
|
40
40
|
barBarHeight,
|
|
41
41
|
barFontSize,
|
|
42
42
|
barHumanReadableLocation,
|
|
43
|
+
idempotencyKey,
|
|
43
44
|
useSandbox = true
|
|
44
45
|
}) {
|
|
45
46
|
if (!reasonL1) {
|
|
@@ -142,7 +143,8 @@ export async function createTransaction({
|
|
|
142
143
|
const headers = {
|
|
143
144
|
'Authorization': `Bearer ${tokenData.token}`,
|
|
144
145
|
'Content-Type': 'application/json',
|
|
145
|
-
'Api-Version': '1' // Required: current API version
|
|
146
|
+
'Api-Version': '1', // Required: current API version
|
|
147
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
146
148
|
};
|
|
147
149
|
|
|
148
150
|
try {
|
|
@@ -160,6 +162,7 @@ export async function createTransaction({
|
|
|
160
162
|
success: true,
|
|
161
163
|
transaction: response.data,
|
|
162
164
|
requestId: response.headers['x-request-id'],
|
|
165
|
+
replayed: response.headers?.['idempotent-replayed'] === 'true',
|
|
163
166
|
timestamp: new Date().toISOString()
|
|
164
167
|
};
|
|
165
168
|
} catch (error) {
|
|
@@ -255,7 +258,9 @@ agreement with payware. Three fields, all optional:
|
|
|
255
258
|
characters. payware records it and never interprets it: no format, no uniqueness enforcement, and
|
|
256
259
|
nothing about pricing or attribution depends on it.
|
|
257
260
|
- \`terminalManufacturer\` - device manufacturer as the terminal reports it. Max 64 chars, no control
|
|
258
|
-
characters. Recorded for provenance
|
|
261
|
+
characters. Recorded for provenance. payware's internal attribution review counts each producer's
|
|
262
|
+
sales by reported manufacturer, so a build running on another vendor's hardware stands out; it is
|
|
263
|
+
never blocked.
|
|
259
264
|
|
|
260
265
|
Two things worth knowing:
|
|
261
266
|
1. **It never changes what the merchant is charged.** The producer's share comes out of payware's own
|
|
@@ -269,6 +274,11 @@ ISV's software is running on that producer's hardware.`,
|
|
|
269
274
|
inputSchema: {
|
|
270
275
|
type: "object",
|
|
271
276
|
properties: {
|
|
277
|
+
idempotencyKey: {
|
|
278
|
+
type: "string",
|
|
279
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
280
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
281
|
+
},
|
|
272
282
|
type: {
|
|
273
283
|
type: "string",
|
|
274
284
|
enum: ["PLAIN", "QR", "BARCODE"],
|
|
@@ -446,6 +456,7 @@ ISV's software is running on that producer's hardware.`,
|
|
|
446
456
|
barBarHeight,
|
|
447
457
|
barFontSize,
|
|
448
458
|
barHumanReadableLocation,
|
|
459
|
+
idempotencyKey,
|
|
449
460
|
useSandbox = true
|
|
450
461
|
} = args;
|
|
451
462
|
|
|
@@ -490,6 +501,7 @@ ISV's software is running on that producer's hardware.`,
|
|
|
490
501
|
barBarHeight,
|
|
491
502
|
barFontSize,
|
|
492
503
|
barHumanReadableLocation,
|
|
504
|
+
idempotencyKey,
|
|
493
505
|
useSandbox
|
|
494
506
|
});
|
|
495
507
|
|
|
@@ -25,6 +25,7 @@ export async function processTransaction({
|
|
|
25
25
|
paymentMethod,
|
|
26
26
|
partnerId,
|
|
27
27
|
privateKey,
|
|
28
|
+
idempotencyKey,
|
|
28
29
|
useSandbox = true
|
|
29
30
|
}) {
|
|
30
31
|
if (!transactionId) {
|
|
@@ -80,7 +81,8 @@ export async function processTransaction({
|
|
|
80
81
|
const headers = {
|
|
81
82
|
'Authorization': `Bearer ${tokenData.token}`,
|
|
82
83
|
'Content-Type': 'application/json',
|
|
83
|
-
'Api-Version': '1'
|
|
84
|
+
'Api-Version': '1', // Required: current API version
|
|
85
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
84
86
|
};
|
|
85
87
|
|
|
86
88
|
try {
|
|
@@ -96,6 +98,7 @@ export async function processTransaction({
|
|
|
96
98
|
success: true,
|
|
97
99
|
transaction: response.data,
|
|
98
100
|
requestId: response.headers['x-request-id'],
|
|
101
|
+
replayed: response.headers?.['idempotent-replayed'] === 'true',
|
|
99
102
|
timestamp: new Date().toISOString()
|
|
100
103
|
};
|
|
101
104
|
} catch (error) {
|
|
@@ -138,6 +141,11 @@ export const processTransactionTool = {
|
|
|
138
141
|
type: "object",
|
|
139
142
|
additionalProperties: false,
|
|
140
143
|
properties: {
|
|
144
|
+
idempotencyKey: {
|
|
145
|
+
type: "string",
|
|
146
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
147
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
148
|
+
},
|
|
141
149
|
transactionId: {
|
|
142
150
|
type: "string",
|
|
143
151
|
description: "Transaction ID to process. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'pl' (placement: pays as its product, and the payment is attributed to the placement), 'ps' (soundbite)",
|
|
@@ -236,6 +244,7 @@ export const processTransactionTool = {
|
|
|
236
244
|
paymentMethod,
|
|
237
245
|
partnerId = getPartnerIdSafe(),
|
|
238
246
|
privateKey = getPrivateKeySafe(args.useSandbox ?? true),
|
|
247
|
+
idempotencyKey,
|
|
239
248
|
useSandbox = true
|
|
240
249
|
} = args;
|
|
241
250
|
|
|
@@ -274,6 +283,7 @@ export const processTransactionTool = {
|
|
|
274
283
|
paymentMethod,
|
|
275
284
|
partnerId,
|
|
276
285
|
privateKey,
|
|
286
|
+
idempotencyKey,
|
|
277
287
|
useSandbox
|
|
278
288
|
});
|
|
279
289
|
|
|
@@ -334,7 +344,7 @@ ${JSON.stringify(result.error.details || result.error, null, 2)}
|
|
|
334
344
|
**Timestamp:** ${result.timestamp}
|
|
335
345
|
|
|
336
346
|
**Common Issues:**
|
|
337
|
-
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found
|
|
347
|
+
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found. **ERR_TRANSACTION_EXPIRED** (also 404): its time to live has run out and it is closed as unpaid
|
|
338
348
|
2. **ERR_UNKNOWN_ROLE**: Transaction generated by payee (can't process own transaction)
|
|
339
349
|
3. **ERR_ALREADY_PROCESSED**: Transaction already processed
|
|
340
350
|
4. **ERR_SPECIFYING_AMOUNT_NOT_ALLOWED**: Amount exceeds transaction limit
|
|
@@ -37,6 +37,7 @@ export async function createPITransaction({
|
|
|
37
37
|
barBarHeight,
|
|
38
38
|
barFontSize,
|
|
39
39
|
barHumanReadableLocation,
|
|
40
|
+
idempotencyKey,
|
|
40
41
|
useSandbox = true
|
|
41
42
|
}) {
|
|
42
43
|
if (!role || !['SRC', 'DST'].includes(role)) {
|
|
@@ -122,7 +123,8 @@ export async function createPITransaction({
|
|
|
122
123
|
const headers = {
|
|
123
124
|
'Authorization': `Bearer ${tokenData.token}`,
|
|
124
125
|
'Content-Type': 'application/json',
|
|
125
|
-
'Api-Version': '1' // Required: current API version
|
|
126
|
+
'Api-Version': '1', // Required: current API version
|
|
127
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
try {
|
|
@@ -139,6 +141,7 @@ export async function createPITransaction({
|
|
|
139
141
|
success: true,
|
|
140
142
|
transaction: response.data,
|
|
141
143
|
requestId: response.headers['x-request-id'],
|
|
144
|
+
replayed: response.headers?.['idempotent-replayed'] === 'true',
|
|
142
145
|
timestamp: new Date().toISOString()
|
|
143
146
|
};
|
|
144
147
|
} catch (error) {
|
|
@@ -185,6 +188,11 @@ export const createPITransactionTool = {
|
|
|
185
188
|
inputSchema: {
|
|
186
189
|
type: "object",
|
|
187
190
|
properties: {
|
|
191
|
+
idempotencyKey: {
|
|
192
|
+
type: "string",
|
|
193
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
194
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
195
|
+
},
|
|
188
196
|
role: {
|
|
189
197
|
type: "string",
|
|
190
198
|
enum: ["SRC", "DST"],
|
|
@@ -348,6 +356,7 @@ export const createPITransactionTool = {
|
|
|
348
356
|
barBarHeight,
|
|
349
357
|
barFontSize,
|
|
350
358
|
barHumanReadableLocation,
|
|
359
|
+
idempotencyKey,
|
|
351
360
|
useSandbox = true
|
|
352
361
|
} = args;
|
|
353
362
|
|
|
@@ -397,6 +406,7 @@ export const createPITransactionTool = {
|
|
|
397
406
|
barBarHeight,
|
|
398
407
|
barFontSize,
|
|
399
408
|
barHumanReadableLocation,
|
|
409
|
+
idempotencyKey,
|
|
400
410
|
useSandbox
|
|
401
411
|
});
|
|
402
412
|
|
|
@@ -313,7 +313,7 @@ ${JSON.stringify(result.error.details || result.error, null, 2)}
|
|
|
313
313
|
**Timestamp:** ${result.timestamp}
|
|
314
314
|
|
|
315
315
|
**Common Finalization Issues:**
|
|
316
|
-
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found
|
|
316
|
+
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found. **ERR_TRANSACTION_EXPIRED** (also 404): the time to live ran out before the finalize arrived, and the transaction is closed as unpaid
|
|
317
317
|
2. **ERR_TRANSACTION_NOT_PROCESSED**: Transaction hasn't been processed yet
|
|
318
318
|
3. **ERR_ALREADY_PROCESSED**: Transaction already finalized
|
|
319
319
|
4. **ERR_INVALID_STATUS**: Invalid status value provided
|
|
@@ -28,6 +28,7 @@ export async function processPITransaction({
|
|
|
28
28
|
deliveryAddress,
|
|
29
29
|
// Payment method for POI transactions (Payment Choice Architecture)
|
|
30
30
|
paymentMethod,
|
|
31
|
+
idempotencyKey,
|
|
31
32
|
useSandbox = true
|
|
32
33
|
}) {
|
|
33
34
|
if (!transactionId) {
|
|
@@ -85,7 +86,8 @@ export async function processPITransaction({
|
|
|
85
86
|
const headers = {
|
|
86
87
|
'Authorization': `Bearer ${tokenData.token}`,
|
|
87
88
|
'Content-Type': 'application/json',
|
|
88
|
-
'Api-Version': '1'
|
|
89
|
+
'Api-Version': '1', // Required: current API version
|
|
90
|
+
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey })
|
|
89
91
|
};
|
|
90
92
|
|
|
91
93
|
try {
|
|
@@ -101,6 +103,7 @@ export async function processPITransaction({
|
|
|
101
103
|
success: true,
|
|
102
104
|
transaction: response.data,
|
|
103
105
|
requestId: response.headers['x-request-id'],
|
|
106
|
+
replayed: response.headers?.['idempotent-replayed'] === 'true',
|
|
104
107
|
timestamp: new Date().toISOString()
|
|
105
108
|
};
|
|
106
109
|
} catch (error) {
|
|
@@ -148,6 +151,11 @@ export const processPITransactionTool = {
|
|
|
148
151
|
inputSchema: {
|
|
149
152
|
type: "object",
|
|
150
153
|
properties: {
|
|
154
|
+
idempotencyKey: {
|
|
155
|
+
type: "string",
|
|
156
|
+
description: "Optional. Sent as the Idempotency-Key header. Use one value per payment (a UUID is typical) and the same value on every retry of it: a retry with the same key and body within 24 hours returns the transaction the first call created instead of a new one, and the result reports replayed: true. The same key with a different body is refused (422 ERR_IDEMPOTENCY_KEY_REUSED); a retry while the first call still runs gets 409 ERR_IDEMPOTENCY_KEY_IN_PROGRESS.",
|
|
157
|
+
pattern: "^[\\x21-\\x7E]{1,255}$"
|
|
158
|
+
},
|
|
151
159
|
transactionId: {
|
|
152
160
|
type: "string",
|
|
153
161
|
description: "Transaction ID to process. Format: 2-char prefix + 8-char ID. Supports: 'pw' (standard), 'pr' (product), 'pl' (placement: pays as its product, and the payment is attributed to the placement), 'ps' (soundbite)",
|
|
@@ -294,6 +302,7 @@ export const processPITransactionTool = {
|
|
|
294
302
|
privateKey = getPrivateKeySafe(args.useSandbox ?? true),
|
|
295
303
|
paymentMethod,
|
|
296
304
|
deliveryAddress,
|
|
305
|
+
idempotencyKey,
|
|
297
306
|
useSandbox = true
|
|
298
307
|
} = args;
|
|
299
308
|
|
|
@@ -340,6 +349,7 @@ export const processPITransactionTool = {
|
|
|
340
349
|
privateKey,
|
|
341
350
|
paymentMethod,
|
|
342
351
|
deliveryAddress,
|
|
352
|
+
idempotencyKey,
|
|
343
353
|
useSandbox
|
|
344
354
|
});
|
|
345
355
|
|
|
@@ -404,7 +414,7 @@ ${JSON.stringify(result.error.details || result.error, null, 2)}
|
|
|
404
414
|
**Timestamp:** ${result.timestamp}
|
|
405
415
|
|
|
406
416
|
**Common Payment Institution Issues:**
|
|
407
|
-
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found
|
|
417
|
+
1. **ERR_MISSING_TRANSACTION**: Transaction ID not found. **ERR_TRANSACTION_EXPIRED** (also 404): its time to live has run out and it is closed as unpaid
|
|
408
418
|
2. **ERR_ALREADY_PROCESSED**: Transaction already processed
|
|
409
419
|
3. **ERR_MISSING_PARTNER_ACCOUNT**: Account parameter missing or empty
|
|
410
420
|
4. **ERR_MISSING_FRIENDLY_NAME**: Friendly name parameter missing
|