@codespar/sdk 0.16.9 → 0.16.10
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.
|
@@ -2873,7 +2873,9 @@ export interface paths {
|
|
|
2873
2873
|
};
|
|
2874
2874
|
/**
|
|
2875
2875
|
* List approvals held for review
|
|
2876
|
-
* @description The
|
|
2876
|
+
* @description The holds, newest first.
|
|
2877
|
+
*
|
|
2878
|
+
* **What a key sees.** A project API key or an OAuth token reads only the holds raised under ITS OWN project, and only their status: `tool_input`, the held request itself, is not in the response. A hold raised outside any project is not a key's either. The dashboard (service auth) reads the whole organization's queue with `tool_input`, because the approver works there.
|
|
2877
2879
|
*
|
|
2878
2880
|
* **Without `status`, you get only the `pending` ones**, not all of them. It is the useful default for an operator queue, and the trap for anyone expecting a history: ask for `status=approved,denied` to see what has already been decided.
|
|
2879
2881
|
*
|
|
@@ -2911,8 +2913,8 @@ export interface paths {
|
|
|
2911
2913
|
matched_rule_name: string;
|
|
2912
2914
|
/** @description The held call, in whatever form the lane that raised the hold writes. There is no single format: see the operation description before matching on it. */
|
|
2913
2915
|
tool_name: string;
|
|
2914
|
-
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. */
|
|
2915
|
-
tool_input
|
|
2916
|
+
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. ABSENT unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
2917
|
+
tool_input?: {
|
|
2916
2918
|
[key: string]: unknown;
|
|
2917
2919
|
};
|
|
2918
2920
|
/** @enum {string} */
|
|
@@ -2990,7 +2992,7 @@ export interface paths {
|
|
|
2990
2992
|
*
|
|
2991
2993
|
* **`reason` is required for both decisions.** Up to 8000 characters, and whitespace alone does not count: the audit trail of a human decision with no written reason is worth nothing later.
|
|
2992
2994
|
*
|
|
2993
|
-
* **Deciding takes a PERSON,
|
|
2995
|
+
* **Deciding takes a PERSON, through the dashboard.** Only service auth (the dashboard) may call this. A project API key or an OAuth token is refused with `bearer_token_cannot_decide` before the body is read, even when it carries a user token: a key or token proves which integration is calling, never that a person looked at the hold. On the dashboard's call the approver's user token has to come with it, be verifiable, and its identity has to match the one the header asserts. That is what separates `the organization decided` from `someone with the key decided`.
|
|
2994
2996
|
*
|
|
2995
2997
|
* **A decision already taken is 409, and an expired one is 410.** In both cases the full approval comes in the body, so the caller can see who decided what without a second read.
|
|
2996
2998
|
*/
|
|
@@ -3033,8 +3035,8 @@ export interface paths {
|
|
|
3033
3035
|
matched_rule_name: string;
|
|
3034
3036
|
/** @description The held call, in whatever form the lane that raised the hold writes. There is no single format: see the operation description before matching on it. */
|
|
3035
3037
|
tool_name: string;
|
|
3036
|
-
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. */
|
|
3037
|
-
tool_input
|
|
3038
|
+
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. ABSENT unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
3039
|
+
tool_input?: {
|
|
3038
3040
|
[key: string]: unknown;
|
|
3039
3041
|
};
|
|
3040
3042
|
/** @enum {string} */
|
|
@@ -3077,7 +3079,7 @@ export interface paths {
|
|
|
3077
3079
|
};
|
|
3078
3080
|
};
|
|
3079
3081
|
};
|
|
3080
|
-
/** @description The caller cannot decide. `bearer_token_cannot_decide` when
|
|
3082
|
+
/** @description The caller cannot decide. `bearer_token_cannot_decide` when the request is not the dashboard's (service auth): a project API key or an OAuth token, with or without a user token; `user_token_required`, `user_token_invalid` and `user_token_identity_mismatch` when the user token is missing, does not verify, or does not match the identity asserted in the header; `insufficient_role` when the person is below admin. Raw body. */
|
|
3081
3083
|
403: {
|
|
3082
3084
|
headers: {
|
|
3083
3085
|
[name: string]: unknown;
|
|
@@ -3125,8 +3127,8 @@ export interface paths {
|
|
|
3125
3127
|
matched_rule_name: string;
|
|
3126
3128
|
/** @description The held call, in whatever form the lane that raised the hold writes. There is no single format: see the operation description before matching on it. */
|
|
3127
3129
|
tool_name: string;
|
|
3128
|
-
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. */
|
|
3129
|
-
tool_input
|
|
3130
|
+
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. ABSENT unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
3131
|
+
tool_input?: {
|
|
3130
3132
|
[key: string]: unknown;
|
|
3131
3133
|
};
|
|
3132
3134
|
/** @enum {string} */
|
|
@@ -3175,8 +3177,8 @@ export interface paths {
|
|
|
3175
3177
|
matched_rule_name: string;
|
|
3176
3178
|
/** @description The held call, in whatever form the lane that raised the hold writes. There is no single format: see the operation description before matching on it. */
|
|
3177
3179
|
tool_name: string;
|
|
3178
|
-
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. */
|
|
3179
|
-
tool_input
|
|
3180
|
+
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. ABSENT unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
3181
|
+
tool_input?: {
|
|
3180
3182
|
[key: string]: unknown;
|
|
3181
3183
|
};
|
|
3182
3184
|
/** @enum {string} */
|
|
@@ -3247,7 +3249,7 @@ export interface paths {
|
|
|
3247
3249
|
* Approval queue health
|
|
3248
3250
|
* @description How deep this organization's approval queue is, how long the oldest hold has been waiting, and whether the sweeps are running.
|
|
3249
3251
|
*
|
|
3250
|
-
* `pending_count` and `oldest_pending_age_seconds` are computed over the caller's own organization, and the second is null exactly when the first is 0: both come from the same `status = 'pending'` filter over the same rows.
|
|
3252
|
+
* `pending_count` and `oldest_pending_age_seconds` are computed over the caller's own organization for the dashboard (service auth), and over the caller's own PROJECT for an API key or an OAuth token, the same rows the list shows it. The second is null exactly when the first is 0: both come from the same `status = 'pending'` filter over the same rows.
|
|
3251
3253
|
*
|
|
3252
3254
|
* `last_sweep_at` IS NOT SCOPED TO THE CALLER, and cannot be. It is the newest run of the expiry and orphan sweeps for the whole deployment: the table it reads holds one row per sweep type and carries no organization column, so the value moves for reasons that have nothing to do with this organization. Read it as 'the sweeps are alive here', never as 'my queue was swept'. Null means neither sweep has ever recorded a run.
|
|
3253
3255
|
*
|
|
@@ -3308,9 +3310,11 @@ export interface paths {
|
|
|
3308
3310
|
};
|
|
3309
3311
|
/**
|
|
3310
3312
|
* Read one approval
|
|
3311
|
-
* @description One held call
|
|
3313
|
+
* @description One held call. The dashboard gets it with the arguments recorded when it was held; an API key or an OAuth token gets its status only.
|
|
3314
|
+
*
|
|
3315
|
+
* SCOPE. The lookup matches the id AND the caller's organization, so an id from another organization answers 404 rather than 403: a 403 would confirm the id exists, which is what a caller sweeping ids is asking. For an API key or an OAuth token it also matches the credential's project, the way the agent-facing poll at `GET /v1/approvals/{id}/status` does: a hold raised under a sibling project, or outside any project, is the same 404. The dashboard (service auth) reads any hold in the organization.
|
|
3312
3316
|
*
|
|
3313
|
-
*
|
|
3317
|
+
* `tool_input` is ABSENT for an API key or an OAuth token: it is the held request itself, which can carry a Pix key, a CPF/CNPJ or account data, and the approver who needs it reads it on the dashboard.
|
|
3314
3318
|
*
|
|
3315
3319
|
* `tool_input` IS NOT THE CALL. It is what the lane that raised the hold recorded, and two things happen to it on the way in. A hold raised on the session execute path carries `{}`, because that path hands the policy engine no tool input at all and the engine stores an empty object when it gets none. A hold raised on the proxy path carries `{ server, method, endpoint, body, params, headers }`, with the `authorization` and `cookie` request headers removed before the row is written. So an empty object here means 'this lane records nothing', not 'the agent sent nothing'.
|
|
3316
3320
|
*
|
|
@@ -3350,8 +3354,8 @@ export interface paths {
|
|
|
3350
3354
|
matched_rule_name: string;
|
|
3351
3355
|
/** @description The held call, in whatever form the lane that raised the hold writes. There is no single format: see the operation description before matching on it. */
|
|
3352
3356
|
tool_name: string;
|
|
3353
|
-
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. */
|
|
3354
|
-
tool_input
|
|
3357
|
+
/** @description The arguments as RECORDED, which is not always the arguments as sent. Empty for a hold raised on the session execute path, and header-stripped on the proxy path. ABSENT unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
3358
|
+
tool_input?: {
|
|
3355
3359
|
[key: string]: unknown;
|
|
3356
3360
|
};
|
|
3357
3361
|
/** @enum {string} */
|
|
@@ -5159,6 +5163,26 @@ export interface paths {
|
|
|
5159
5163
|
};
|
|
5160
5164
|
};
|
|
5161
5165
|
};
|
|
5166
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
5167
|
+
422: {
|
|
5168
|
+
headers: {
|
|
5169
|
+
[name: string]: unknown;
|
|
5170
|
+
};
|
|
5171
|
+
content: {
|
|
5172
|
+
"application/json": {
|
|
5173
|
+
error: {
|
|
5174
|
+
/** @enum {string} */
|
|
5175
|
+
code: "ofb_not_live";
|
|
5176
|
+
message: string;
|
|
5177
|
+
details?: {
|
|
5178
|
+
[key: string]: unknown;
|
|
5179
|
+
};
|
|
5180
|
+
};
|
|
5181
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
5182
|
+
request_id: string | null;
|
|
5183
|
+
};
|
|
5184
|
+
};
|
|
5185
|
+
};
|
|
5162
5186
|
/** @description `consent_disappeared`: the row was written and could not be read back. Do not retry blind; both the row and the bank-side consent may exist. */
|
|
5163
5187
|
500: {
|
|
5164
5188
|
headers: {
|
|
@@ -5199,7 +5223,11 @@ export interface paths {
|
|
|
5199
5223
|
};
|
|
5200
5224
|
};
|
|
5201
5225
|
};
|
|
5202
|
-
/**
|
|
5226
|
+
/**
|
|
5227
|
+
* @description `consent_lock_timeout`: another request is issuing a consent for this consumer at this bank and the wait ended without an answer, so NOTHING WAS DECIDED. We do not know whether a sibling holds the grant, and saying so is why this is not the 409. `details.retriable` is true. No consent row was created; a bank-side consent was, and is orphaned.
|
|
5228
|
+
*
|
|
5229
|
+
* `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted.
|
|
5230
|
+
*/
|
|
5203
5231
|
503: {
|
|
5204
5232
|
headers: {
|
|
5205
5233
|
[name: string]: unknown;
|
|
@@ -5208,7 +5236,7 @@ export interface paths {
|
|
|
5208
5236
|
"application/json": {
|
|
5209
5237
|
error: {
|
|
5210
5238
|
/** @enum {string} */
|
|
5211
|
-
code: "consent_lock_timeout";
|
|
5239
|
+
code: "consent_lock_timeout" | "ofb_adapter_unavailable";
|
|
5212
5240
|
message: string;
|
|
5213
5241
|
details?: {
|
|
5214
5242
|
[key: string]: unknown;
|
|
@@ -7947,7 +7975,7 @@ export interface paths {
|
|
|
7947
7975
|
requestBody?: {
|
|
7948
7976
|
content: {
|
|
7949
7977
|
"application/json": {
|
|
7950
|
-
/** @description The identity fields the provider asks for: `documentNumber` (CPF or CNPJ), full name, date of birth, address. Passed through as an object: the handler does not validate it field by field here, and whatever the provider refuses comes back in the provider's own refusal. */
|
|
7978
|
+
/** @description The identity fields the provider asks for: `documentNumber` (CPF or CNPJ), full name, date of birth, address. Passed through as an object: the handler does not validate it field by field here, and whatever the provider refuses comes back in the provider's own refusal. Two exceptions are checked before anything is sent: the document's check digits, and, for a natural person (CPF) in a live project, `financialDetails` = `{ declaredIncome, occupation, netWorth }` in the provider's codes. That is the titular's own declaration, and CodeSpar never fills it in for them. */
|
|
7951
7979
|
buyer: {
|
|
7952
7980
|
[key: string]: unknown;
|
|
7953
7981
|
};
|
|
@@ -7995,7 +8023,7 @@ export interface paths {
|
|
|
7995
8023
|
};
|
|
7996
8024
|
};
|
|
7997
8025
|
};
|
|
7998
|
-
/** @description The body did not match the schema,
|
|
8026
|
+
/** @description The body did not match the schema, the document did not pass the check, or a natural person's onboarding in a live project came without `buyer.financialDetails` (one issue per missing code, its `path` naming it). BARE BODY, not the `{ error: { code, message } }` envelope: this handler writes its failure inline and there is no `request_id`. */
|
|
7999
8027
|
400: {
|
|
8000
8028
|
headers: {
|
|
8001
8029
|
[name: string]: unknown;
|
|
@@ -9333,7 +9361,7 @@ export interface paths {
|
|
|
9333
9361
|
ok: false;
|
|
9334
9362
|
provider: string;
|
|
9335
9363
|
/** @enum {string} */
|
|
9336
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9364
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9337
9365
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9338
9366
|
detail?: string;
|
|
9339
9367
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9368,7 +9396,7 @@ export interface paths {
|
|
|
9368
9396
|
ok: false;
|
|
9369
9397
|
provider: string;
|
|
9370
9398
|
/** @enum {string} */
|
|
9371
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9399
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9372
9400
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9373
9401
|
detail?: string;
|
|
9374
9402
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9398,7 +9426,7 @@ export interface paths {
|
|
|
9398
9426
|
ok: false;
|
|
9399
9427
|
provider: string;
|
|
9400
9428
|
/** @enum {string} */
|
|
9401
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9429
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9402
9430
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9403
9431
|
detail?: string;
|
|
9404
9432
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9417,7 +9445,7 @@ export interface paths {
|
|
|
9417
9445
|
};
|
|
9418
9446
|
};
|
|
9419
9447
|
};
|
|
9420
|
-
/** @description `not_connected`. There is no usable credential to test: no active connection for this project and provider, or the vault returned nothing for the reference it holds. This body carries the extra `hint` / `alternative` steer. Or `connection_expired`: the project has an authorization-code OAuth connection whose access token passed its expiry, and nothing refreshes it, so the fix is to reconnect. That body carries `expires_at` and no sandbox steer. */
|
|
9448
|
+
/** @description `not_connected`. There is no usable credential to test: no active connection for this project and provider, or the vault returned nothing for the reference it holds. This body carries the extra `hint` / `alternative` steer. Or `connection_expired`: the project has an authorization-code OAuth connection whose access token passed its expiry, and nothing refreshes it, so the fix is to reconnect. That body carries `expires_at` and no sandbox steer. Or `shared_sandbox_live_project_refused`: the project's connection for this provider is the platform's shared SANDBOX credential, which serves test projects only, and this is a live project (or a live-mode call). Nothing was sent to the provider; the fix is to connect the project's own credential. */
|
|
9421
9449
|
424: {
|
|
9422
9450
|
headers: {
|
|
9423
9451
|
[name: string]: unknown;
|
|
@@ -9428,7 +9456,7 @@ export interface paths {
|
|
|
9428
9456
|
ok: false;
|
|
9429
9457
|
provider: string;
|
|
9430
9458
|
/** @enum {string} */
|
|
9431
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9459
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9432
9460
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9433
9461
|
detail?: string;
|
|
9434
9462
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9458,7 +9486,7 @@ export interface paths {
|
|
|
9458
9486
|
ok: false;
|
|
9459
9487
|
provider: string;
|
|
9460
9488
|
/** @enum {string} */
|
|
9461
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9489
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9462
9490
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9463
9491
|
detail?: string;
|
|
9464
9492
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9488,7 +9516,7 @@ export interface paths {
|
|
|
9488
9516
|
ok: false;
|
|
9489
9517
|
provider: string;
|
|
9490
9518
|
/** @enum {string} */
|
|
9491
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9519
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9492
9520
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9493
9521
|
detail?: string;
|
|
9494
9522
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -9518,7 +9546,7 @@ export interface paths {
|
|
|
9518
9546
|
ok: false;
|
|
9519
9547
|
provider: string;
|
|
9520
9548
|
/** @enum {string} */
|
|
9521
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable";
|
|
9549
|
+
error: "server_unknown" | "verify_unsupported" | "not_connected" | "connection_expired" | "provider_rejected" | "provider_unreachable" | "redirect_not_followed" | "endpoint_missing" | "test_venue_unavailable" | "shared_sandbox_live_project_refused";
|
|
9522
9550
|
/** @description Whose sentence this is depends on the code, and the difference matters. On `provider_rejected` and `provider_unreachable` it is up to 256 characters of the PROVIDER's own response body, or the transport error. On the others it is text we wrote, naming what is missing on our side. It is absent on `redirect_not_followed`, and on the `server_unknown` and `endpoint_missing` refusals that carry nothing but the code. On `test_venue_unavailable` it names the catalog file and the field to declare, and it is the one refusal here that is about the project's ENVIRONMENT rather than its connection: the identical request from a `live` project reaches the provider. */
|
|
9523
9551
|
detail?: string;
|
|
9524
9552
|
/** @description The provider's HTTP status, present only when a round trip completed: on `provider_rejected`, `redirect_not_followed`, and the `provider_unreachable` that came from a response rather than from a transport failure. Its ABSENCE on a 502 is the signal that nothing was reached at all. */
|
|
@@ -14866,7 +14894,7 @@ export interface paths {
|
|
|
14866
14894
|
*
|
|
14867
14895
|
* **There is no read route for the outcome.** An `attempt_id` that answered `psp_dispatch_uncertain` has no endpoint to ask about afterwards. Keep the `attempt_id` and present it again: the lifecycle is idempotent on it and answers the state that attempt stopped in, instead of firing a second one. Do NOT restart the same intent under a fresh `attempt_id`. That is how a payment gets made twice. A retry of an attempt that already holds money is not evaluated against the organization's policy rules again, so a budget or a rate limit cannot refuse the retry that finds out what happened.
|
|
14868
14896
|
*
|
|
14869
|
-
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail and
|
|
14897
|
+
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail, quote and approval, returns the ORIGINAL 200 body verbatim (same `transactionId`, same receipt) with `idempotent_replay: true`, and nothing is dispatched, held, sealed or published. This holds on every rail and in test mode alike, and while the organization is paused, since the answer moves no money. Presenting it with any of those parameters changed is `attempt_id_conflict`. Idempotency is opt-in: a request without an `attempt_id` is its own payment and is never replayed, so two spends under one mandate are two payments. Send an `attempt_id` to make a retry safe.
|
|
14870
14898
|
*/
|
|
14871
14899
|
post: {
|
|
14872
14900
|
parameters: {
|
|
@@ -14891,6 +14919,7 @@ export interface paths {
|
|
|
14891
14919
|
ted?: components["schemas"]["TedDestination"];
|
|
14892
14920
|
quote?: components["schemas"]["SpendQuote"];
|
|
14893
14921
|
actor?: components["schemas"]["PaymentActor"];
|
|
14922
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
14894
14923
|
};
|
|
14895
14924
|
};
|
|
14896
14925
|
};
|
|
@@ -14904,7 +14933,7 @@ export interface paths {
|
|
|
14904
14933
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
14905
14934
|
};
|
|
14906
14935
|
};
|
|
14907
|
-
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in
|
|
14936
|
+
/** @description The body did not match the schema (`invalid_body`), `approval` is malformed (`invalid_approval_hash`), `quote.at` is not an RFC 3339 timestamp with an offset in UTC years 0001-9999 (`invalid_receipt_timestamp`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in any of these cases. `attempt_id_required`: the body names no `attempt_id` and the deployment enforces one (`ATTEMPT_ID_REQUIRED_ENFORCE`); add a stable id and reuse it on every retry of that payment. It is checked AFTER the body is valid, so a request that is both malformed and id-less is answered `invalid_approval_hash`, `invalid_receipt_timestamp` or `invalid_body` first. */
|
|
14908
14937
|
400: {
|
|
14909
14938
|
headers: {
|
|
14910
14939
|
[name: string]: unknown;
|
|
@@ -14913,7 +14942,7 @@ export interface paths {
|
|
|
14913
14942
|
"application/json": {
|
|
14914
14943
|
error: {
|
|
14915
14944
|
/** @enum {string} */
|
|
14916
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
14945
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
14917
14946
|
message: string;
|
|
14918
14947
|
details?: {
|
|
14919
14948
|
[key: string]: unknown;
|
|
@@ -15095,7 +15124,7 @@ export interface paths {
|
|
|
15095
15124
|
*
|
|
15096
15125
|
* **There is no read route for the outcome.** An `attempt_id` that answered `psp_dispatch_uncertain` has no endpoint to ask about afterwards. Keep the `attempt_id` and present it again: the lifecycle is idempotent on it and answers the state that attempt stopped in, instead of firing a second one. Do NOT restart the same intent under a fresh `attempt_id`. That is how a payment gets made twice. A retry of an attempt that already holds money is not evaluated against the organization's policy rules again, so a budget or a rate limit cannot refuse the retry that finds out what happened.
|
|
15097
15126
|
*
|
|
15098
|
-
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail and
|
|
15127
|
+
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail, quote and approval, returns the ORIGINAL 200 body verbatim (same `transactionId`, same receipt) with `idempotent_replay: true`, and nothing is dispatched, held, sealed or published. This holds on every rail and in test mode alike, and while the organization is paused, since the answer moves no money. Presenting it with any of those parameters changed is `attempt_id_conflict`. Idempotency is opt-in: a request without an `attempt_id` is its own payment and is never replayed, so two spends under one mandate are two payments. Send an `attempt_id` to make a retry safe.
|
|
15099
15128
|
*/
|
|
15100
15129
|
post: {
|
|
15101
15130
|
parameters: {
|
|
@@ -15119,6 +15148,7 @@ export interface paths {
|
|
|
15119
15148
|
ted?: components["schemas"]["TedDestination"];
|
|
15120
15149
|
quote?: components["schemas"]["SpendQuote"];
|
|
15121
15150
|
actor?: components["schemas"]["PaymentActor"];
|
|
15151
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
15122
15152
|
};
|
|
15123
15153
|
};
|
|
15124
15154
|
};
|
|
@@ -15132,7 +15162,7 @@ export interface paths {
|
|
|
15132
15162
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
15133
15163
|
};
|
|
15134
15164
|
};
|
|
15135
|
-
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in
|
|
15165
|
+
/** @description The body did not match the schema (`invalid_body`), `approval` is malformed (`invalid_approval_hash`), `quote.at` is not an RFC 3339 timestamp with an offset in UTC years 0001-9999 (`invalid_receipt_timestamp`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in any of these cases. `attempt_id_required`: the body names no `attempt_id` and the deployment enforces one (`ATTEMPT_ID_REQUIRED_ENFORCE`); add a stable id and reuse it on every retry of that payment. It is checked AFTER the body is valid, so a request that is both malformed and id-less is answered `invalid_approval_hash`, `invalid_receipt_timestamp` or `invalid_body` first. */
|
|
15136
15166
|
400: {
|
|
15137
15167
|
headers: {
|
|
15138
15168
|
[name: string]: unknown;
|
|
@@ -15141,7 +15171,7 @@ export interface paths {
|
|
|
15141
15171
|
"application/json": {
|
|
15142
15172
|
error: {
|
|
15143
15173
|
/** @enum {string} */
|
|
15144
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
15174
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
15145
15175
|
message: string;
|
|
15146
15176
|
details?: {
|
|
15147
15177
|
[key: string]: unknown;
|
|
@@ -15277,7 +15307,7 @@ export interface paths {
|
|
|
15277
15307
|
*
|
|
15278
15308
|
* **There is no read route for the outcome.** An `attempt_id` that answered `psp_dispatch_uncertain` has no endpoint to ask about afterwards. Keep the `attempt_id` and present it again: the lifecycle is idempotent on it and answers the state that attempt stopped in, instead of firing a second one. Do NOT restart the same intent under a fresh `attempt_id`. That is how a payment gets made twice. A retry of an attempt that already holds money is not evaluated against the organization's policy rules again, so a budget or a rate limit cannot refuse the retry that finds out what happened.
|
|
15279
15309
|
*
|
|
15280
|
-
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail and
|
|
15310
|
+
* **A settled attempt answers its recorded response.** Presenting the `attempt_id` of an attempt that already settled, with the same amount, payee, mandate, rail, quote and approval, returns the ORIGINAL 200 body verbatim (same `transactionId`, same receipt) with `idempotent_replay: true`, and nothing is dispatched, held, sealed or published. This holds on every rail and in test mode alike, and while the organization is paused, since the answer moves no money. Presenting it with any of those parameters changed is `attempt_id_conflict`. Idempotency is opt-in: a request without an `attempt_id` is its own payment and is never replayed, so two spends under one mandate are two payments. Send an `attempt_id` to make a retry safe.
|
|
15281
15311
|
*/
|
|
15282
15312
|
post: {
|
|
15283
15313
|
parameters: {
|
|
@@ -15299,6 +15329,7 @@ export interface paths {
|
|
|
15299
15329
|
ted?: components["schemas"]["TedDestination"];
|
|
15300
15330
|
quote?: components["schemas"]["SpendQuote"];
|
|
15301
15331
|
actor?: components["schemas"]["PaymentActor"];
|
|
15332
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
15302
15333
|
};
|
|
15303
15334
|
};
|
|
15304
15335
|
};
|
|
@@ -15312,7 +15343,7 @@ export interface paths {
|
|
|
15312
15343
|
"text/event-stream": string;
|
|
15313
15344
|
};
|
|
15314
15345
|
};
|
|
15315
|
-
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in
|
|
15346
|
+
/** @description The body did not match the schema (`invalid_body`), `approval` is malformed (`invalid_approval_hash`), `quote.at` is not an RFC 3339 timestamp with an offset in UTC years 0001-9999 (`invalid_receipt_timestamp`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in any of these cases. `attempt_id_required`: the body names no `attempt_id` and the deployment enforces one (`ATTEMPT_ID_REQUIRED_ENFORCE`); add a stable id and reuse it on every retry of that payment. It is checked AFTER the body is valid, so a request that is both malformed and id-less is answered `invalid_approval_hash`, `invalid_receipt_timestamp` or `invalid_body` first. */
|
|
15316
15347
|
400: {
|
|
15317
15348
|
headers: {
|
|
15318
15349
|
[name: string]: unknown;
|
|
@@ -15321,7 +15352,7 @@ export interface paths {
|
|
|
15321
15352
|
"application/json": {
|
|
15322
15353
|
error: {
|
|
15323
15354
|
/** @enum {string} */
|
|
15324
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
15355
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
15325
15356
|
message: string;
|
|
15326
15357
|
details?: {
|
|
15327
15358
|
[key: string]: unknown;
|
|
@@ -18115,7 +18146,10 @@ export interface paths {
|
|
|
18115
18146
|
nonce: string;
|
|
18116
18147
|
scope: string;
|
|
18117
18148
|
currency: string;
|
|
18149
|
+
/** @description The mandate's HMAC signature. It must not be shared with a third party. Chains of version 1-3 seal it, which is why only the tenant can recompute those; a version 4 chain seals `sig_sha256` instead. */
|
|
18118
18150
|
sig: string;
|
|
18151
|
+
/** @description SHA-256 over the UTF-8 bytes of `sig`, lowercase hex. What a version 4 chain seals in the mandate link, so a third party recomputes it without ever seeing `sig`. */
|
|
18152
|
+
sig_sha256: string;
|
|
18119
18153
|
};
|
|
18120
18154
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
18121
18155
|
quote: {
|
|
@@ -18127,6 +18161,15 @@ export interface paths {
|
|
|
18127
18161
|
sig: string | null;
|
|
18128
18162
|
at: string | null;
|
|
18129
18163
|
} | null;
|
|
18164
|
+
/**
|
|
18165
|
+
* @description Present ONLY when the spend carried an `approval`; absent otherwise, and absent on every receipt sealed before the field existed. The value is sealed into `chain` as its own link (chain version 4), so it is covered by `receipt_sig` and `receipt_sig_ed25519`.
|
|
18166
|
+
*
|
|
18167
|
+
* It is a SEALED CLAIM by the caller, NOT a server-side approval check: the server validated its shape and nothing else. It proves this payment was sealed together with this hash, not that anybody approved anything, and not who did — the approver's identity stays in the caller's own approval artifact.
|
|
18168
|
+
*/
|
|
18169
|
+
approval?: {
|
|
18170
|
+
items_hash: string;
|
|
18171
|
+
batch_hash: string | null;
|
|
18172
|
+
};
|
|
18130
18173
|
payment: {
|
|
18131
18174
|
rail: string;
|
|
18132
18175
|
provider: string | null;
|
|
@@ -18161,7 +18204,20 @@ export interface paths {
|
|
|
18161
18204
|
nfe_chave: string | null;
|
|
18162
18205
|
at: string | null;
|
|
18163
18206
|
} | null;
|
|
18207
|
+
/**
|
|
18208
|
+
* @description SHA-256 (64 lowercase hex) over the UTF-8 bytes of the RFC 8785 (JCS) canonical JSON of `{ "v": chain_version, "links": [...] }`. Every value a link needs is in this read, so the chain can be recomputed from it and bound to `receipt_sig_ed25519`. The links, in order, each left out when it does not apply:
|
|
18209
|
+
*
|
|
18210
|
+
* 1. mandate — always: `id`, `nonce`, `scope`, `currency`, then `sig` (v1-v3) or `sig_sha256` (v4), from `mandate`.
|
|
18211
|
+
* 2. quote — when `quote` is not null: `seller`, `resource`, `price_minor`, `payee`, `session_id`, `sig`, `at`, nulls included.
|
|
18212
|
+
* 3. approval — v4 only: `items_hash`, `batch_hash` (null when absent).
|
|
18213
|
+
* 4. payment — always: `rail`, `provider`, `tx_id`, `amount_minor`, `attempt_id`, `money_moved`, `at`, plus each of `amount_atomic`, `amount_authorized`, `amount_charged`, `amount_refunded`, `metering`, `sandbox` only when present and not null.
|
|
18214
|
+
* 5. delivery — when `delivery` is not null: `result`, `proof`, `kind`, `nfe_chave`, `at`.
|
|
18215
|
+
*
|
|
18216
|
+
* Values are copied as read; timestamps are RFC 3339 UTC with milliseconds. The same recipe is served as data in `chain_recipe` on the unauthenticated `/.well-known/codespar-receipt-keys.json`. Recomputing needs `quote.payee` unmasked, and a v1-v3 chain needs `mandate.sig`, so only the tenant can recompute those. The Ed25519 signing string does not change with the version: it covers this digest.
|
|
18217
|
+
*/
|
|
18164
18218
|
chain: string;
|
|
18219
|
+
/** @description The chain format `chain` was computed with: 4 when `approval` is present; else 3 when `payment.amount_authorized` is present; else 2 when `payment.amount_atomic` is not null; else 1. A receipt keeps the version it was sealed under. */
|
|
18220
|
+
chain_version: number;
|
|
18165
18221
|
receipt_sig: string;
|
|
18166
18222
|
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
18167
18223
|
receipt_sig_ed25519: string | null;
|
|
@@ -18238,7 +18294,10 @@ export interface paths {
|
|
|
18238
18294
|
nonce: string;
|
|
18239
18295
|
scope: string;
|
|
18240
18296
|
currency: string;
|
|
18297
|
+
/** @description The mandate's HMAC signature. It must not be shared with a third party. Chains of version 1-3 seal it, which is why only the tenant can recompute those; a version 4 chain seals `sig_sha256` instead. */
|
|
18241
18298
|
sig: string;
|
|
18299
|
+
/** @description SHA-256 over the UTF-8 bytes of `sig`, lowercase hex. What a version 4 chain seals in the mandate link, so a third party recomputes it without ever seeing `sig`. */
|
|
18300
|
+
sig_sha256: string;
|
|
18242
18301
|
};
|
|
18243
18302
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
18244
18303
|
quote: {
|
|
@@ -18250,6 +18309,15 @@ export interface paths {
|
|
|
18250
18309
|
sig: string | null;
|
|
18251
18310
|
at: string | null;
|
|
18252
18311
|
} | null;
|
|
18312
|
+
/**
|
|
18313
|
+
* @description Present ONLY when the spend carried an `approval`; absent otherwise, and absent on every receipt sealed before the field existed. The value is sealed into `chain` as its own link (chain version 4), so it is covered by `receipt_sig` and `receipt_sig_ed25519`.
|
|
18314
|
+
*
|
|
18315
|
+
* It is a SEALED CLAIM by the caller, NOT a server-side approval check: the server validated its shape and nothing else. It proves this payment was sealed together with this hash, not that anybody approved anything, and not who did — the approver's identity stays in the caller's own approval artifact.
|
|
18316
|
+
*/
|
|
18317
|
+
approval?: {
|
|
18318
|
+
items_hash: string;
|
|
18319
|
+
batch_hash: string | null;
|
|
18320
|
+
};
|
|
18253
18321
|
payment: {
|
|
18254
18322
|
rail: string;
|
|
18255
18323
|
provider: string | null;
|
|
@@ -18284,7 +18352,20 @@ export interface paths {
|
|
|
18284
18352
|
nfe_chave: string | null;
|
|
18285
18353
|
at: string | null;
|
|
18286
18354
|
} | null;
|
|
18355
|
+
/**
|
|
18356
|
+
* @description SHA-256 (64 lowercase hex) over the UTF-8 bytes of the RFC 8785 (JCS) canonical JSON of `{ "v": chain_version, "links": [...] }`. Every value a link needs is in this read, so the chain can be recomputed from it and bound to `receipt_sig_ed25519`. The links, in order, each left out when it does not apply:
|
|
18357
|
+
*
|
|
18358
|
+
* 1. mandate — always: `id`, `nonce`, `scope`, `currency`, then `sig` (v1-v3) or `sig_sha256` (v4), from `mandate`.
|
|
18359
|
+
* 2. quote — when `quote` is not null: `seller`, `resource`, `price_minor`, `payee`, `session_id`, `sig`, `at`, nulls included.
|
|
18360
|
+
* 3. approval — v4 only: `items_hash`, `batch_hash` (null when absent).
|
|
18361
|
+
* 4. payment — always: `rail`, `provider`, `tx_id`, `amount_minor`, `attempt_id`, `money_moved`, `at`, plus each of `amount_atomic`, `amount_authorized`, `amount_charged`, `amount_refunded`, `metering`, `sandbox` only when present and not null.
|
|
18362
|
+
* 5. delivery — when `delivery` is not null: `result`, `proof`, `kind`, `nfe_chave`, `at`.
|
|
18363
|
+
*
|
|
18364
|
+
* Values are copied as read; timestamps are RFC 3339 UTC with milliseconds. The same recipe is served as data in `chain_recipe` on the unauthenticated `/.well-known/codespar-receipt-keys.json`. Recomputing needs `quote.payee` unmasked, and a v1-v3 chain needs `mandate.sig`, so only the tenant can recompute those. The Ed25519 signing string does not change with the version: it covers this digest.
|
|
18365
|
+
*/
|
|
18287
18366
|
chain: string;
|
|
18367
|
+
/** @description The chain format `chain` was computed with: 4 when `approval` is present; else 3 when `payment.amount_authorized` is present; else 2 when `payment.amount_atomic` is not null; else 1. A receipt keeps the version it was sealed under. */
|
|
18368
|
+
chain_version: number;
|
|
18288
18369
|
receipt_sig: string;
|
|
18289
18370
|
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
18290
18371
|
receipt_sig_ed25519: string | null;
|
|
@@ -20184,6 +20265,10 @@ export interface paths {
|
|
|
20184
20265
|
/** @enum {string} */
|
|
20185
20266
|
kind: "order_confirmation" | "nfe" | "nfse" | "tracking" | "resource" | "merchant_ref" | "pix_e2e";
|
|
20186
20267
|
nfe_chave?: string;
|
|
20268
|
+
/**
|
|
20269
|
+
* Format: date-time
|
|
20270
|
+
* @description When the delivery happened, RFC 3339 with an offset, in UTC years 0001-9999. Sealed into the chain as that instant in UTC with milliseconds. Anything else is refused with `invalid_receipt_timestamp`.
|
|
20271
|
+
*/
|
|
20187
20272
|
at?: string;
|
|
20188
20273
|
};
|
|
20189
20274
|
};
|
|
@@ -20216,7 +20301,10 @@ export interface paths {
|
|
|
20216
20301
|
nonce: string;
|
|
20217
20302
|
scope: string;
|
|
20218
20303
|
currency: string;
|
|
20304
|
+
/** @description The mandate's HMAC signature. It must not be shared with a third party. Chains of version 1-3 seal it, which is why only the tenant can recompute those; a version 4 chain seals `sig_sha256` instead. */
|
|
20219
20305
|
sig: string;
|
|
20306
|
+
/** @description SHA-256 over the UTF-8 bytes of `sig`, lowercase hex. What a version 4 chain seals in the mandate link, so a third party recomputes it without ever seeing `sig`. */
|
|
20307
|
+
sig_sha256: string;
|
|
20220
20308
|
};
|
|
20221
20309
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
20222
20310
|
quote: {
|
|
@@ -20228,6 +20316,15 @@ export interface paths {
|
|
|
20228
20316
|
sig: string | null;
|
|
20229
20317
|
at: string | null;
|
|
20230
20318
|
} | null;
|
|
20319
|
+
/**
|
|
20320
|
+
* @description Present ONLY when the spend carried an `approval`; absent otherwise, and absent on every receipt sealed before the field existed. The value is sealed into `chain` as its own link (chain version 4), so it is covered by `receipt_sig` and `receipt_sig_ed25519`.
|
|
20321
|
+
*
|
|
20322
|
+
* It is a SEALED CLAIM by the caller, NOT a server-side approval check: the server validated its shape and nothing else. It proves this payment was sealed together with this hash, not that anybody approved anything, and not who did — the approver's identity stays in the caller's own approval artifact.
|
|
20323
|
+
*/
|
|
20324
|
+
approval?: {
|
|
20325
|
+
items_hash: string;
|
|
20326
|
+
batch_hash: string | null;
|
|
20327
|
+
};
|
|
20231
20328
|
payment: {
|
|
20232
20329
|
rail: string;
|
|
20233
20330
|
provider: string | null;
|
|
@@ -20262,7 +20359,20 @@ export interface paths {
|
|
|
20262
20359
|
nfe_chave: string | null;
|
|
20263
20360
|
at: string | null;
|
|
20264
20361
|
} | null;
|
|
20362
|
+
/**
|
|
20363
|
+
* @description SHA-256 (64 lowercase hex) over the UTF-8 bytes of the RFC 8785 (JCS) canonical JSON of `{ "v": chain_version, "links": [...] }`. Every value a link needs is in this read, so the chain can be recomputed from it and bound to `receipt_sig_ed25519`. The links, in order, each left out when it does not apply:
|
|
20364
|
+
*
|
|
20365
|
+
* 1. mandate — always: `id`, `nonce`, `scope`, `currency`, then `sig` (v1-v3) or `sig_sha256` (v4), from `mandate`.
|
|
20366
|
+
* 2. quote — when `quote` is not null: `seller`, `resource`, `price_minor`, `payee`, `session_id`, `sig`, `at`, nulls included.
|
|
20367
|
+
* 3. approval — v4 only: `items_hash`, `batch_hash` (null when absent).
|
|
20368
|
+
* 4. payment — always: `rail`, `provider`, `tx_id`, `amount_minor`, `attempt_id`, `money_moved`, `at`, plus each of `amount_atomic`, `amount_authorized`, `amount_charged`, `amount_refunded`, `metering`, `sandbox` only when present and not null.
|
|
20369
|
+
* 5. delivery — when `delivery` is not null: `result`, `proof`, `kind`, `nfe_chave`, `at`.
|
|
20370
|
+
*
|
|
20371
|
+
* Values are copied as read; timestamps are RFC 3339 UTC with milliseconds. The same recipe is served as data in `chain_recipe` on the unauthenticated `/.well-known/codespar-receipt-keys.json`. Recomputing needs `quote.payee` unmasked, and a v1-v3 chain needs `mandate.sig`, so only the tenant can recompute those. The Ed25519 signing string does not change with the version: it covers this digest.
|
|
20372
|
+
*/
|
|
20265
20373
|
chain: string;
|
|
20374
|
+
/** @description The chain format `chain` was computed with: 4 when `approval` is present; else 3 when `payment.amount_authorized` is present; else 2 when `payment.amount_atomic` is not null; else 1. A receipt keeps the version it was sealed under. */
|
|
20375
|
+
chain_version: number;
|
|
20266
20376
|
receipt_sig: string;
|
|
20267
20377
|
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
20268
20378
|
receipt_sig_ed25519: string | null;
|
|
@@ -20276,7 +20386,7 @@ export interface paths {
|
|
|
20276
20386
|
};
|
|
20277
20387
|
};
|
|
20278
20388
|
};
|
|
20279
|
-
/** @description The body did not match the schema
|
|
20389
|
+
/** @description The body did not match the schema (`invalid_body`): most often a `kind` outside the seven accepted values, or a `proof` longer than 500 characters, with Zod's issues in `details.issues`. Or `at` is not an RFC 3339 timestamp with an offset in UTC years 0001-9999 (`invalid_receipt_timestamp`). Nothing was re-sealed in either case. */
|
|
20280
20390
|
400: {
|
|
20281
20391
|
headers: {
|
|
20282
20392
|
[name: string]: unknown;
|
|
@@ -20285,7 +20395,7 @@ export interface paths {
|
|
|
20285
20395
|
"application/json": {
|
|
20286
20396
|
error: {
|
|
20287
20397
|
/** @enum {string} */
|
|
20288
|
-
code: "invalid_body";
|
|
20398
|
+
code: "invalid_body" | "invalid_receipt_timestamp";
|
|
20289
20399
|
message: string;
|
|
20290
20400
|
details?: {
|
|
20291
20401
|
[key: string]: unknown;
|
|
@@ -21072,6 +21182,26 @@ export interface paths {
|
|
|
21072
21182
|
};
|
|
21073
21183
|
};
|
|
21074
21184
|
};
|
|
21185
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
21186
|
+
422: {
|
|
21187
|
+
headers: {
|
|
21188
|
+
[name: string]: unknown;
|
|
21189
|
+
};
|
|
21190
|
+
content: {
|
|
21191
|
+
"application/json": {
|
|
21192
|
+
error: {
|
|
21193
|
+
/** @enum {string} */
|
|
21194
|
+
code: "ofb_not_live";
|
|
21195
|
+
message: string;
|
|
21196
|
+
details?: {
|
|
21197
|
+
[key: string]: unknown;
|
|
21198
|
+
};
|
|
21199
|
+
};
|
|
21200
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21201
|
+
request_id: string | null;
|
|
21202
|
+
};
|
|
21203
|
+
};
|
|
21204
|
+
};
|
|
21075
21205
|
/** @description `missing_bank_consent_id`: the stored consent carries no bank-side id, so there is nothing to finalise. Ours to fix, not yours; quote the request id. */
|
|
21076
21206
|
500: {
|
|
21077
21207
|
headers: {
|
|
@@ -21112,6 +21242,26 @@ export interface paths {
|
|
|
21112
21242
|
};
|
|
21113
21243
|
};
|
|
21114
21244
|
};
|
|
21245
|
+
/** @description `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted. */
|
|
21246
|
+
503: {
|
|
21247
|
+
headers: {
|
|
21248
|
+
[name: string]: unknown;
|
|
21249
|
+
};
|
|
21250
|
+
content: {
|
|
21251
|
+
"application/json": {
|
|
21252
|
+
error: {
|
|
21253
|
+
/** @enum {string} */
|
|
21254
|
+
code: "ofb_adapter_unavailable";
|
|
21255
|
+
message: string;
|
|
21256
|
+
details?: {
|
|
21257
|
+
[key: string]: unknown;
|
|
21258
|
+
};
|
|
21259
|
+
};
|
|
21260
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21261
|
+
request_id: string | null;
|
|
21262
|
+
};
|
|
21263
|
+
};
|
|
21264
|
+
};
|
|
21115
21265
|
};
|
|
21116
21266
|
};
|
|
21117
21267
|
delete?: never;
|
|
@@ -21244,6 +21394,26 @@ export interface paths {
|
|
|
21244
21394
|
};
|
|
21245
21395
|
};
|
|
21246
21396
|
};
|
|
21397
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
21398
|
+
422: {
|
|
21399
|
+
headers: {
|
|
21400
|
+
[name: string]: unknown;
|
|
21401
|
+
};
|
|
21402
|
+
content: {
|
|
21403
|
+
"application/json": {
|
|
21404
|
+
error: {
|
|
21405
|
+
/** @enum {string} */
|
|
21406
|
+
code: "ofb_not_live";
|
|
21407
|
+
message: string;
|
|
21408
|
+
details?: {
|
|
21409
|
+
[key: string]: unknown;
|
|
21410
|
+
};
|
|
21411
|
+
};
|
|
21412
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21413
|
+
request_id: string | null;
|
|
21414
|
+
};
|
|
21415
|
+
};
|
|
21416
|
+
};
|
|
21247
21417
|
/** @description `consent_missing_tokens`: the consent says `authorised` but is missing something the fetch needs. TWO conditions raise it and the code does not distinguish them: no stored access-token pointer, OR no bank-side consent id. The second is not a token, so read the code as `this authorised consent is not usable` rather than as a statement about credentials. Ours to fix, not yours; quote the request id. */
|
|
21248
21418
|
500: {
|
|
21249
21419
|
headers: {
|
|
@@ -21284,6 +21454,26 @@ export interface paths {
|
|
|
21284
21454
|
};
|
|
21285
21455
|
};
|
|
21286
21456
|
};
|
|
21457
|
+
/** @description `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted. */
|
|
21458
|
+
503: {
|
|
21459
|
+
headers: {
|
|
21460
|
+
[name: string]: unknown;
|
|
21461
|
+
};
|
|
21462
|
+
content: {
|
|
21463
|
+
"application/json": {
|
|
21464
|
+
error: {
|
|
21465
|
+
/** @enum {string} */
|
|
21466
|
+
code: "ofb_adapter_unavailable";
|
|
21467
|
+
message: string;
|
|
21468
|
+
details?: {
|
|
21469
|
+
[key: string]: unknown;
|
|
21470
|
+
};
|
|
21471
|
+
};
|
|
21472
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21473
|
+
request_id: string | null;
|
|
21474
|
+
};
|
|
21475
|
+
};
|
|
21476
|
+
};
|
|
21287
21477
|
};
|
|
21288
21478
|
};
|
|
21289
21479
|
delete?: never;
|
|
@@ -22016,6 +22206,26 @@ export interface paths {
|
|
|
22016
22206
|
};
|
|
22017
22207
|
};
|
|
22018
22208
|
};
|
|
22209
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
22210
|
+
422: {
|
|
22211
|
+
headers: {
|
|
22212
|
+
[name: string]: unknown;
|
|
22213
|
+
};
|
|
22214
|
+
content: {
|
|
22215
|
+
"application/json": {
|
|
22216
|
+
error: {
|
|
22217
|
+
/** @enum {string} */
|
|
22218
|
+
code: "ofb_not_live";
|
|
22219
|
+
message: string;
|
|
22220
|
+
details?: {
|
|
22221
|
+
[key: string]: unknown;
|
|
22222
|
+
};
|
|
22223
|
+
};
|
|
22224
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22225
|
+
request_id: string | null;
|
|
22226
|
+
};
|
|
22227
|
+
};
|
|
22228
|
+
};
|
|
22019
22229
|
/** @description `consent_disappeared`: the row was written and could not be read back. Do not retry blind; both the row and the bank-side consent may exist. */
|
|
22020
22230
|
500: {
|
|
22021
22231
|
headers: {
|
|
@@ -22056,7 +22266,11 @@ export interface paths {
|
|
|
22056
22266
|
};
|
|
22057
22267
|
};
|
|
22058
22268
|
};
|
|
22059
|
-
/**
|
|
22269
|
+
/**
|
|
22270
|
+
* @description `consent_lock_timeout`: another request is issuing a consent for this consumer at this bank and the wait ended without an answer, so NOTHING WAS DECIDED. We do not know whether a sibling holds the grant, and saying so is why this is not the 409. `details.retriable` is true. No consent row was created; a bank-side consent was, and is orphaned.
|
|
22271
|
+
*
|
|
22272
|
+
* `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted.
|
|
22273
|
+
*/
|
|
22060
22274
|
503: {
|
|
22061
22275
|
headers: {
|
|
22062
22276
|
[name: string]: unknown;
|
|
@@ -22065,7 +22279,7 @@ export interface paths {
|
|
|
22065
22279
|
"application/json": {
|
|
22066
22280
|
error: {
|
|
22067
22281
|
/** @enum {string} */
|
|
22068
|
-
code: "consent_lock_timeout";
|
|
22282
|
+
code: "consent_lock_timeout" | "ofb_adapter_unavailable";
|
|
22069
22283
|
message: string;
|
|
22070
22284
|
details?: {
|
|
22071
22285
|
[key: string]: unknown;
|
|
@@ -22224,6 +22438,26 @@ export interface paths {
|
|
|
22224
22438
|
};
|
|
22225
22439
|
};
|
|
22226
22440
|
};
|
|
22441
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
22442
|
+
422: {
|
|
22443
|
+
headers: {
|
|
22444
|
+
[name: string]: unknown;
|
|
22445
|
+
};
|
|
22446
|
+
content: {
|
|
22447
|
+
"application/json": {
|
|
22448
|
+
error: {
|
|
22449
|
+
/** @enum {string} */
|
|
22450
|
+
code: "ofb_not_live";
|
|
22451
|
+
message: string;
|
|
22452
|
+
details?: {
|
|
22453
|
+
[key: string]: unknown;
|
|
22454
|
+
};
|
|
22455
|
+
};
|
|
22456
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22457
|
+
request_id: string | null;
|
|
22458
|
+
};
|
|
22459
|
+
};
|
|
22460
|
+
};
|
|
22227
22461
|
/** @description `missing_bank_consent_id`: the stored consent carries no bank-side id, so there is nothing to finalise. Ours to fix, not yours; quote the request id. */
|
|
22228
22462
|
500: {
|
|
22229
22463
|
headers: {
|
|
@@ -22264,6 +22498,26 @@ export interface paths {
|
|
|
22264
22498
|
};
|
|
22265
22499
|
};
|
|
22266
22500
|
};
|
|
22501
|
+
/** @description `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted. */
|
|
22502
|
+
503: {
|
|
22503
|
+
headers: {
|
|
22504
|
+
[name: string]: unknown;
|
|
22505
|
+
};
|
|
22506
|
+
content: {
|
|
22507
|
+
"application/json": {
|
|
22508
|
+
error: {
|
|
22509
|
+
/** @enum {string} */
|
|
22510
|
+
code: "ofb_adapter_unavailable";
|
|
22511
|
+
message: string;
|
|
22512
|
+
details?: {
|
|
22513
|
+
[key: string]: unknown;
|
|
22514
|
+
};
|
|
22515
|
+
};
|
|
22516
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22517
|
+
request_id: string | null;
|
|
22518
|
+
};
|
|
22519
|
+
};
|
|
22520
|
+
};
|
|
22267
22521
|
};
|
|
22268
22522
|
};
|
|
22269
22523
|
delete?: never;
|
|
@@ -22391,6 +22645,26 @@ export interface paths {
|
|
|
22391
22645
|
};
|
|
22392
22646
|
};
|
|
22393
22647
|
};
|
|
22648
|
+
/** @description `ofb_not_live`: this is a LIVE project and the deployment has no real Open Finance adapter, only the stub, which serves test projects. TERMINAL for this project: use a test project. Nothing was written and no bank was contacted. */
|
|
22649
|
+
422: {
|
|
22650
|
+
headers: {
|
|
22651
|
+
[name: string]: unknown;
|
|
22652
|
+
};
|
|
22653
|
+
content: {
|
|
22654
|
+
"application/json": {
|
|
22655
|
+
error: {
|
|
22656
|
+
/** @enum {string} */
|
|
22657
|
+
code: "ofb_not_live";
|
|
22658
|
+
message: string;
|
|
22659
|
+
details?: {
|
|
22660
|
+
[key: string]: unknown;
|
|
22661
|
+
};
|
|
22662
|
+
};
|
|
22663
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22664
|
+
request_id: string | null;
|
|
22665
|
+
};
|
|
22666
|
+
};
|
|
22667
|
+
};
|
|
22394
22668
|
/** @description `consent_missing_tokens`: the consent says `authorised` but is missing something the fetch needs. TWO conditions raise it and the code does not distinguish them: no stored access-token pointer, OR no bank-side consent id. The second is not a token, so read the code as `this authorised consent is not usable` rather than as a statement about credentials. Ours to fix, not yours; quote the request id. */
|
|
22395
22669
|
500: {
|
|
22396
22670
|
headers: {
|
|
@@ -22431,6 +22705,26 @@ export interface paths {
|
|
|
22431
22705
|
};
|
|
22432
22706
|
};
|
|
22433
22707
|
};
|
|
22708
|
+
/** @description `ofb_adapter_unavailable`: the Open Finance adapter this deployment selects cannot serve (`details.reason`: `missing_credentials`, `not_implemented` or `unknown_mode`). Ours to fix, not yours; nothing was written and no bank was contacted. */
|
|
22709
|
+
503: {
|
|
22710
|
+
headers: {
|
|
22711
|
+
[name: string]: unknown;
|
|
22712
|
+
};
|
|
22713
|
+
content: {
|
|
22714
|
+
"application/json": {
|
|
22715
|
+
error: {
|
|
22716
|
+
/** @enum {string} */
|
|
22717
|
+
code: "ofb_adapter_unavailable";
|
|
22718
|
+
message: string;
|
|
22719
|
+
details?: {
|
|
22720
|
+
[key: string]: unknown;
|
|
22721
|
+
};
|
|
22722
|
+
};
|
|
22723
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22724
|
+
request_id: string | null;
|
|
22725
|
+
};
|
|
22726
|
+
};
|
|
22727
|
+
};
|
|
22434
22728
|
};
|
|
22435
22729
|
};
|
|
22436
22730
|
delete?: never;
|
|
@@ -23657,6 +23951,8 @@ export interface paths {
|
|
|
23657
23951
|
* @description DEPRECATED alias of `GET /v1/approvals` (ent#979), kept for two releases. Same handler, same scope; switch the path and nothing else changes.
|
|
23658
23952
|
*
|
|
23659
23953
|
* **Without `status` you get only the `pending` ones**, not all of them. Ask for `status=approved,denied` to see what has already been decided. The response is an array, with no envelope and no cursor. An `{orgId}` that is not the credential's own is 404 before any read.
|
|
23954
|
+
*
|
|
23955
|
+
* An API key or an OAuth token lists only its own project's holds, without `tool_input`; the dashboard (service auth) lists the whole organization's, with it.
|
|
23660
23956
|
*/
|
|
23661
23957
|
get: {
|
|
23662
23958
|
parameters: {
|
|
@@ -23688,8 +23984,8 @@ export interface paths {
|
|
|
23688
23984
|
matched_rule_id: string;
|
|
23689
23985
|
matched_rule_name: string;
|
|
23690
23986
|
tool_name: string;
|
|
23691
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23692
|
-
tool_input
|
|
23987
|
+
/** @description The tool arguments the rule held for review, verbatim. Absent unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
23988
|
+
tool_input?: {
|
|
23693
23989
|
[key: string]: unknown;
|
|
23694
23990
|
};
|
|
23695
23991
|
/**
|
|
@@ -23764,7 +24060,7 @@ export interface paths {
|
|
|
23764
24060
|
* @deprecated
|
|
23765
24061
|
* @description DEPRECATED alias of `POST /v1/approvals/{id}/decide` (ent#979), kept for two releases. Same handler, same scope; switch the path and nothing else changes.
|
|
23766
24062
|
*
|
|
23767
|
-
* `reason` is required in both directions, up to 8000 characters, and whitespace alone is refused. Deciding requires a PERSON: a
|
|
24063
|
+
* `reason` is required in both directions, up to 8000 characters, and whitespace alone is refused. Deciding requires a PERSON, through the dashboard: only service auth may call it, and a project API key or an OAuth token gets `bearer_token_cannot_decide` before the body is read, with or without a user token. Already decided is 409 and expired is 410, both with the full approval in the body.
|
|
23768
24064
|
*/
|
|
23769
24065
|
post: {
|
|
23770
24066
|
parameters: {
|
|
@@ -23801,8 +24097,8 @@ export interface paths {
|
|
|
23801
24097
|
matched_rule_id: string;
|
|
23802
24098
|
matched_rule_name: string;
|
|
23803
24099
|
tool_name: string;
|
|
23804
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23805
|
-
tool_input
|
|
24100
|
+
/** @description The tool arguments the rule held for review, verbatim. Absent unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
24101
|
+
tool_input?: {
|
|
23806
24102
|
[key: string]: unknown;
|
|
23807
24103
|
};
|
|
23808
24104
|
/**
|
|
@@ -23843,7 +24139,7 @@ export interface paths {
|
|
|
23843
24139
|
};
|
|
23844
24140
|
};
|
|
23845
24141
|
};
|
|
23846
|
-
/** @description The caller cannot decide: a
|
|
24142
|
+
/** @description The caller cannot decide: not the dashboard (a project API key or an OAuth token, with or without a user token), a user token that is missing/invalid/mismatched, or a person below admin. Bare body. */
|
|
23847
24143
|
403: {
|
|
23848
24144
|
headers: {
|
|
23849
24145
|
[name: string]: unknown;
|
|
@@ -23887,8 +24183,8 @@ export interface paths {
|
|
|
23887
24183
|
matched_rule_id: string;
|
|
23888
24184
|
matched_rule_name: string;
|
|
23889
24185
|
tool_name: string;
|
|
23890
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23891
|
-
tool_input
|
|
24186
|
+
/** @description The tool arguments the rule held for review, verbatim. Absent unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
24187
|
+
tool_input?: {
|
|
23892
24188
|
[key: string]: unknown;
|
|
23893
24189
|
};
|
|
23894
24190
|
/**
|
|
@@ -23931,8 +24227,8 @@ export interface paths {
|
|
|
23931
24227
|
matched_rule_id: string;
|
|
23932
24228
|
matched_rule_name: string;
|
|
23933
24229
|
tool_name: string;
|
|
23934
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23935
|
-
tool_input
|
|
24230
|
+
/** @description The tool arguments the rule held for review, verbatim. Absent unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
24231
|
+
tool_input?: {
|
|
23936
24232
|
[key: string]: unknown;
|
|
23937
24233
|
};
|
|
23938
24234
|
/**
|
|
@@ -24002,7 +24298,7 @@ export interface paths {
|
|
|
24002
24298
|
* @deprecated
|
|
24003
24299
|
* @description DEPRECATED alias of `GET /v1/approvals/{id}` (ent#979), kept for two releases. Same handler, same `approvals:read` scope; switch the path and nothing else changes.
|
|
24004
24300
|
*
|
|
24005
|
-
* The whole row a rule parked for a human, `tool_input` included, which is what makes the decision reviewable rather than a yes or no on an id. Two selected columns are deliberately off the wire: `decision_history`, and `metadata`, where the decision path records whether the approver's identity was verified or merely asserted.
|
|
24301
|
+
* The whole row a rule parked for a human, `tool_input` included, which is what makes the decision reviewable rather than a yes or no on an id. That is the dashboard's view (service auth). An API key or an OAuth token reads only holds raised under its own project, and without `tool_input`; any other hold is the same 404 as one that does not exist. Two selected columns are deliberately off the wire: `decision_history`, and `metadata`, where the decision path records whether the approver's identity was verified or merely asserted.
|
|
24006
24302
|
*
|
|
24007
24303
|
* An approval belonging to another org is indistinguishable from one that does not exist: both are 404, and an `{orgId}` that is not the credential's own org is 404 before any read.
|
|
24008
24304
|
*/
|
|
@@ -24033,8 +24329,8 @@ export interface paths {
|
|
|
24033
24329
|
matched_rule_id: string;
|
|
24034
24330
|
matched_rule_name: string;
|
|
24035
24331
|
tool_name: string;
|
|
24036
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
24037
|
-
tool_input
|
|
24332
|
+
/** @description The tool arguments the rule held for review, verbatim. Absent unless the caller is the dashboard (service auth): an API key or an OAuth token never receives it. */
|
|
24333
|
+
tool_input?: {
|
|
24038
24334
|
[key: string]: unknown;
|
|
24039
24335
|
};
|
|
24040
24336
|
/**
|
|
@@ -24092,7 +24388,7 @@ export interface paths {
|
|
|
24092
24388
|
* @deprecated
|
|
24093
24389
|
* @description DEPRECATED alias of `GET /v1/approvals/health` (ent#979), kept for two releases. Same handler, same `approvals:read` scope.
|
|
24094
24390
|
*
|
|
24095
|
-
* The operator snapshot behind a queue alarm: how many approvals are pending for this org and how long the oldest has been waiting. `status` is a verdict on the sweeps only (`degraded` when `last_sweep_at` is null or older than 30 minutes, `status_reason` says which), never on queue depth, so alert on `oldest_pending_age_seconds` for that. Both counters are null or zero on an empty queue.
|
|
24391
|
+
* The operator snapshot behind a queue alarm: how many approvals are pending for this org (for an API key or an OAuth token, for its own project) and how long the oldest has been waiting. `status` is a verdict on the sweeps only (`degraded` when `last_sweep_at` is null or older than 30 minutes, `status_reason` says which), never on queue depth, so alert on `oldest_pending_age_seconds` for that. Both counters are null or zero on an empty queue.
|
|
24096
24392
|
*
|
|
24097
24393
|
* `last_sweep_at` is PLATFORM-WIDE, not per org: it is the last run of the expiry and orphan sweeps across the deployment. A stale value there means approvals may be sitting past their `expires_at` without being marked expired anywhere, which is a different fault from a deep queue.
|
|
24098
24394
|
*
|
|
@@ -25861,7 +26157,7 @@ export interface paths {
|
|
|
25861
26157
|
};
|
|
25862
26158
|
};
|
|
25863
26159
|
};
|
|
25864
|
-
/** @description The dashboard path named no admin, or a token that did not verify. Bare `{ error, remediation }` body. */
|
|
26160
|
+
/** @description The dashboard path named no admin, or a token that did not verify; or the credential is an OAuth token, which cannot pause (`bearer_token_cannot_decide`: only a bearer key, as itself, or the dashboard, as a person, presses the switch). Bare `{ error, remediation }` body. */
|
|
25865
26161
|
403: {
|
|
25866
26162
|
headers: {
|
|
25867
26163
|
[name: string]: unknown;
|
|
@@ -29920,7 +30216,7 @@ export interface paths {
|
|
|
29920
30216
|
* Complete the review of a payable
|
|
29921
30217
|
* @description A person records what they decided about a payable that is `NEEDS_REVIEW`, and the payable comes out `READY` or `REJECTED`. There is no third outcome and no partial review: a call that leaves anything blocking is refused and writes nothing, so resolve every item of `review` in one call.
|
|
29922
30218
|
*
|
|
29923
|
-
* **Who may review.** A verified human. Forward the reviewer's Clerk session token in `x-codespar-user-token` on a service-auth request; that user must be an `admin` of the organization.
|
|
30219
|
+
* **Who may review.** A verified human. Forward the reviewer's Clerk session token in `x-codespar-user-token` on a service-auth request; that user must be an `admin` of the organization. Any other credential, a project API key or an OAuth token, is refused (`bearer_token_cannot_decide`) even with a user token: a key or token proves which service is calling, never which person confirmed, and the audit event names the person.
|
|
29924
30220
|
*
|
|
29925
30221
|
* **The ordinary review is an empty one.** `resolutions: []` releases a payable that no check failed and that only a review trigger holds — typically `new_supplier`, a supplier this project has never paid. The person is still recorded as the author.
|
|
29926
30222
|
*
|
|
@@ -30492,7 +30788,7 @@ export interface paths {
|
|
|
30492
30788
|
};
|
|
30493
30789
|
};
|
|
30494
30790
|
};
|
|
30495
|
-
/** @description The reviewer was not established. `bearer_token_cannot_decide`: a project API key cannot review. `user_token_required`: no token was forwarded. `user_token_invalid`: the token did not verify — mint a fresh one. `user_token_identity_mismatch`: `x-codespar-user` names somebody else. `insufficient_role`: that user is not an admin of the organization. */
|
|
30791
|
+
/** @description The reviewer was not established. `bearer_token_cannot_decide`: the credential is not service auth (a project API key or an OAuth token), which cannot review. `user_token_required`: no token was forwarded. `user_token_invalid`: the token did not verify — mint a fresh one. `user_token_identity_mismatch`: `x-codespar-user` names somebody else. `insufficient_role`: that user is not an admin of the organization. */
|
|
30496
30792
|
403: {
|
|
30497
30793
|
headers: {
|
|
30498
30794
|
[name: string]: unknown;
|
|
@@ -33930,7 +34226,7 @@ export interface paths {
|
|
|
33930
34226
|
};
|
|
33931
34227
|
};
|
|
33932
34228
|
};
|
|
33933
|
-
/** @description Failed Dependency — no usable credential for this server. `reason` is the resolver's own outcome. */
|
|
34229
|
+
/** @description Failed Dependency — no usable credential for this server. `reason` is the resolver's own outcome. Or `shared_sandbox_live_project_refused`: the project's connection for this server is the platform's shared SANDBOX credential, which serves test projects only, and this is a live project or a live-mode call; `reason` is that environment. Answered whether or not `PROXY_REQUIRE_CONNECTION` is set, nothing is sent upstream, and the fix is to connect the project's own credential (p2-proxy#5). */
|
|
33934
34230
|
424: {
|
|
33935
34231
|
headers: {
|
|
33936
34232
|
[name: string]: unknown;
|
|
@@ -33943,6 +34239,12 @@ export interface paths {
|
|
|
33943
34239
|
reason: "server_unknown" | "not_connected" | "endpoint_missing";
|
|
33944
34240
|
server: string;
|
|
33945
34241
|
message: string;
|
|
34242
|
+
} | {
|
|
34243
|
+
/** @enum {string} */
|
|
34244
|
+
error: "shared_sandbox_live_project_refused";
|
|
34245
|
+
reason: string;
|
|
34246
|
+
server: string;
|
|
34247
|
+
message: string;
|
|
33946
34248
|
};
|
|
33947
34249
|
};
|
|
33948
34250
|
};
|
|
@@ -36675,6 +36977,10 @@ export interface components {
|
|
|
36675
36977
|
price_minor: number;
|
|
36676
36978
|
payee: string;
|
|
36677
36979
|
session_id?: string;
|
|
36980
|
+
/**
|
|
36981
|
+
* Format: date-time
|
|
36982
|
+
* @description When the offer was presented, RFC 3339 with an offset, in UTC years 0001-9999. Sealed into the receipt's chain as that instant in UTC with milliseconds. Anything else is refused with `invalid_receipt_timestamp` before anything is read, held or sent.
|
|
36983
|
+
*/
|
|
36678
36984
|
at?: string;
|
|
36679
36985
|
};
|
|
36680
36986
|
/** @description WHO triggered this spend, recorded on the receipt and read back from it. Optional, and absence is a real answer: a spend that sends no actor records `null`, and nothing is ever inferred from `agent_id` — that field names the agent the mandate was SIGNED for, which is an authority, not an event. A person acting through WhatsApp under an agent's mandate and the agent acting unattended are the same row without this field. */
|
|
@@ -36693,6 +36999,17 @@ export interface components {
|
|
|
36693
36999
|
/** @description Where the person acted from: `whatsapp`, `dashboard`, `cli`. */
|
|
36694
37000
|
channel?: string;
|
|
36695
37001
|
};
|
|
37002
|
+
/**
|
|
37003
|
+
* @description The hash of what the caller says a person approved: `items_hash` for this spend's lines, and for a batch `batch_hash` over the whole presented list. When present it is SEALED into the receipt's signed chain as its own link (chain version 4), so it cannot be stripped or altered afterwards without breaking both `receipt_sig` and `receipt_sig_ed25519`, and the receipt reads return it.
|
|
37004
|
+
*
|
|
37005
|
+
* It is a SEALED CLAIM by the caller, NOT a server-side approval check. The server only validates the shape; it never interprets the value, never compares it with anything and never refuses a spend because of it. It proves that this payment was sealed together with this hash, so whoever holds the approval artifact can recompute the hash and hold it against the receipt. It does not prove that anybody approved anything, or who. A malformed value, or a key other than these two, is refused with `invalid_approval_hash` before anything is read, held or sent. Part of what makes two requests with one `attempt_id` the same payment: a repeat with a different `approval` is `attempt_id_conflict`.
|
|
37006
|
+
*/
|
|
37007
|
+
SpendApproval: {
|
|
37008
|
+
/** @description A SHA-256 digest in lowercase hex, optionally prefixed `sha256:`. Sealed exactly as sent. */
|
|
37009
|
+
items_hash: string;
|
|
37010
|
+
/** @description A SHA-256 digest in lowercase hex, optionally prefixed `sha256:`. Sealed exactly as sent. */
|
|
37011
|
+
batch_hash?: string;
|
|
37012
|
+
};
|
|
36696
37013
|
};
|
|
36697
37014
|
responses: never;
|
|
36698
37015
|
parameters: never;
|