@codespar/sdk 0.16.8 → 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.
|
@@ -835,7 +835,7 @@ export interface paths {
|
|
|
835
835
|
put?: never;
|
|
836
836
|
/**
|
|
837
837
|
* Open a session
|
|
838
|
-
* @description A session is the unit an agent's tool calls, policy evaluations and audit entries hang off. `servers` names the connected MCP servers it may reach (
|
|
838
|
+
* @description A session is the unit an agent's tool calls, policy evaluations and audit entries hang off. `servers` names the connected MCP servers it may reach (0–20), and every id must be one `GET /v1/servers` returns for this project — an id that is not gets 400 `unknown_servers` with the offenders listed, which is a different body from the schema `invalid_body` above it.
|
|
839
839
|
*
|
|
840
840
|
* `mocks` and `chaos` are accepted only on a project whose environment is `test`: a live-environment project gets 403 mocks_not_permitted, a payload over 64 KiB gets 413, and a malformed one gets 400 with RFC 6901 pointers pointing at the offending field.
|
|
841
841
|
*/
|
|
@@ -851,6 +851,8 @@ export interface paths {
|
|
|
851
851
|
"application/json": {
|
|
852
852
|
servers: string[];
|
|
853
853
|
user_id?: string;
|
|
854
|
+
/** @description The registered agent this session acts as (its handle). Approvals raised in the session are attributed to it. Must name an active agent of this org, or the request answers 422. */
|
|
855
|
+
agent_id?: string;
|
|
854
856
|
mocks?: {
|
|
855
857
|
[key: string]: unknown;
|
|
856
858
|
};
|
|
@@ -2791,9 +2793,9 @@ export interface paths {
|
|
|
2791
2793
|
*
|
|
2792
2794
|
* `revoked` is not `retired`. Retired is a graceful exit; revoked is authority withdrawn, possibly adversarial. Both are reachable states and this verb writes the second one.
|
|
2793
2795
|
*
|
|
2794
|
-
* WHAT IT STOPS: the agent can no longer be paid as an `agent:<id>` payee,
|
|
2796
|
+
* WHAT IT STOPS: the agent can no longer be paid as an `agent:<id>` payee, can no longer mint a new KYA-bearing mandate, and can no longer spend under consumer mandates bound to its key: every consumer lane, card included, refuses them. The mandates themselves are not revoked -- the consumer signed them -- they stop clearing the spend-time check.
|
|
2795
2797
|
*
|
|
2796
|
-
* WHAT IT DOES NOT STOP: spending under mandates
|
|
2798
|
+
* WHAT IT DOES NOT STOP: spending under consumer mandates not bound to a key (issued before that binding existed, or while the agent was unregistered), because they name no key a revocation could reach. The deployment can refuse those for every agent (CONSUMER_MANDATE_AGENT_ENFORCE); otherwise, revoke those mandates.
|
|
2797
2799
|
*
|
|
2798
2800
|
* A `{did}` belonging to another org returns 404, not 403: 403 would confirm that the identity exists, which is what a caller sweeping DIDs is asking.
|
|
2799
2801
|
*/
|
|
@@ -2871,7 +2873,9 @@ export interface paths {
|
|
|
2871
2873
|
};
|
|
2872
2874
|
/**
|
|
2873
2875
|
* List approvals held for review
|
|
2874
|
-
* @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.
|
|
2875
2879
|
*
|
|
2876
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.
|
|
2877
2881
|
*
|
|
@@ -2909,8 +2913,8 @@ export interface paths {
|
|
|
2909
2913
|
matched_rule_name: string;
|
|
2910
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. */
|
|
2911
2915
|
tool_name: string;
|
|
2912
|
-
/** @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. */
|
|
2913
|
-
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?: {
|
|
2914
2918
|
[key: string]: unknown;
|
|
2915
2919
|
};
|
|
2916
2920
|
/** @enum {string} */
|
|
@@ -2988,7 +2992,7 @@ export interface paths {
|
|
|
2988
2992
|
*
|
|
2989
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.
|
|
2990
2994
|
*
|
|
2991
|
-
* **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`.
|
|
2992
2996
|
*
|
|
2993
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.
|
|
2994
2998
|
*/
|
|
@@ -3031,8 +3035,8 @@ export interface paths {
|
|
|
3031
3035
|
matched_rule_name: string;
|
|
3032
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. */
|
|
3033
3037
|
tool_name: string;
|
|
3034
|
-
/** @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. */
|
|
3035
|
-
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?: {
|
|
3036
3040
|
[key: string]: unknown;
|
|
3037
3041
|
};
|
|
3038
3042
|
/** @enum {string} */
|
|
@@ -3075,7 +3079,7 @@ export interface paths {
|
|
|
3075
3079
|
};
|
|
3076
3080
|
};
|
|
3077
3081
|
};
|
|
3078
|
-
/** @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. */
|
|
3079
3083
|
403: {
|
|
3080
3084
|
headers: {
|
|
3081
3085
|
[name: string]: unknown;
|
|
@@ -3123,8 +3127,8 @@ export interface paths {
|
|
|
3123
3127
|
matched_rule_name: string;
|
|
3124
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. */
|
|
3125
3129
|
tool_name: string;
|
|
3126
|
-
/** @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. */
|
|
3127
|
-
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?: {
|
|
3128
3132
|
[key: string]: unknown;
|
|
3129
3133
|
};
|
|
3130
3134
|
/** @enum {string} */
|
|
@@ -3173,8 +3177,8 @@ export interface paths {
|
|
|
3173
3177
|
matched_rule_name: string;
|
|
3174
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. */
|
|
3175
3179
|
tool_name: string;
|
|
3176
|
-
/** @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. */
|
|
3177
|
-
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?: {
|
|
3178
3182
|
[key: string]: unknown;
|
|
3179
3183
|
};
|
|
3180
3184
|
/** @enum {string} */
|
|
@@ -3245,7 +3249,7 @@ export interface paths {
|
|
|
3245
3249
|
* Approval queue health
|
|
3246
3250
|
* @description How deep this organization's approval queue is, how long the oldest hold has been waiting, and whether the sweeps are running.
|
|
3247
3251
|
*
|
|
3248
|
-
* `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.
|
|
3249
3253
|
*
|
|
3250
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.
|
|
3251
3255
|
*
|
|
@@ -3306,9 +3310,11 @@ export interface paths {
|
|
|
3306
3310
|
};
|
|
3307
3311
|
/**
|
|
3308
3312
|
* Read one approval
|
|
3309
|
-
* @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.
|
|
3310
3316
|
*
|
|
3311
|
-
*
|
|
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.
|
|
3312
3318
|
*
|
|
3313
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'.
|
|
3314
3320
|
*
|
|
@@ -3348,8 +3354,8 @@ export interface paths {
|
|
|
3348
3354
|
matched_rule_name: string;
|
|
3349
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. */
|
|
3350
3356
|
tool_name: string;
|
|
3351
|
-
/** @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. */
|
|
3352
|
-
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?: {
|
|
3353
3359
|
[key: string]: unknown;
|
|
3354
3360
|
};
|
|
3355
3361
|
/** @enum {string} */
|
|
@@ -5157,6 +5163,26 @@ export interface paths {
|
|
|
5157
5163
|
};
|
|
5158
5164
|
};
|
|
5159
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
|
+
};
|
|
5160
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. */
|
|
5161
5187
|
500: {
|
|
5162
5188
|
headers: {
|
|
@@ -5197,7 +5223,11 @@ export interface paths {
|
|
|
5197
5223
|
};
|
|
5198
5224
|
};
|
|
5199
5225
|
};
|
|
5200
|
-
/**
|
|
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
|
+
*/
|
|
5201
5231
|
503: {
|
|
5202
5232
|
headers: {
|
|
5203
5233
|
[name: string]: unknown;
|
|
@@ -5206,7 +5236,7 @@ export interface paths {
|
|
|
5206
5236
|
"application/json": {
|
|
5207
5237
|
error: {
|
|
5208
5238
|
/** @enum {string} */
|
|
5209
|
-
code: "consent_lock_timeout";
|
|
5239
|
+
code: "consent_lock_timeout" | "ofb_adapter_unavailable";
|
|
5210
5240
|
message: string;
|
|
5211
5241
|
details?: {
|
|
5212
5242
|
[key: string]: unknown;
|
|
@@ -7945,7 +7975,7 @@ export interface paths {
|
|
|
7945
7975
|
requestBody?: {
|
|
7946
7976
|
content: {
|
|
7947
7977
|
"application/json": {
|
|
7948
|
-
/** @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. */
|
|
7949
7979
|
buyer: {
|
|
7950
7980
|
[key: string]: unknown;
|
|
7951
7981
|
};
|
|
@@ -7993,7 +8023,7 @@ export interface paths {
|
|
|
7993
8023
|
};
|
|
7994
8024
|
};
|
|
7995
8025
|
};
|
|
7996
|
-
/** @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`. */
|
|
7997
8027
|
400: {
|
|
7998
8028
|
headers: {
|
|
7999
8029
|
[name: string]: unknown;
|
|
@@ -9331,7 +9361,7 @@ export interface paths {
|
|
|
9331
9361
|
ok: false;
|
|
9332
9362
|
provider: string;
|
|
9333
9363
|
/** @enum {string} */
|
|
9334
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9335
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. */
|
|
9336
9366
|
detail?: string;
|
|
9337
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. */
|
|
@@ -9345,6 +9375,8 @@ export interface paths {
|
|
|
9345
9375
|
alternative?: string;
|
|
9346
9376
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9347
9377
|
caveat?: string;
|
|
9378
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9379
|
+
expires_at?: string;
|
|
9348
9380
|
};
|
|
9349
9381
|
};
|
|
9350
9382
|
};
|
|
@@ -9364,7 +9396,7 @@ export interface paths {
|
|
|
9364
9396
|
ok: false;
|
|
9365
9397
|
provider: string;
|
|
9366
9398
|
/** @enum {string} */
|
|
9367
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9368
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. */
|
|
9369
9401
|
detail?: string;
|
|
9370
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. */
|
|
@@ -9378,6 +9410,8 @@ export interface paths {
|
|
|
9378
9410
|
alternative?: string;
|
|
9379
9411
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9380
9412
|
caveat?: string;
|
|
9413
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9414
|
+
expires_at?: string;
|
|
9381
9415
|
};
|
|
9382
9416
|
};
|
|
9383
9417
|
};
|
|
@@ -9392,7 +9426,7 @@ export interface paths {
|
|
|
9392
9426
|
ok: false;
|
|
9393
9427
|
provider: string;
|
|
9394
9428
|
/** @enum {string} */
|
|
9395
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9396
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. */
|
|
9397
9431
|
detail?: string;
|
|
9398
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. */
|
|
@@ -9406,10 +9440,12 @@ export interface paths {
|
|
|
9406
9440
|
alternative?: string;
|
|
9407
9441
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9408
9442
|
caveat?: string;
|
|
9443
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9444
|
+
expires_at?: string;
|
|
9409
9445
|
};
|
|
9410
9446
|
};
|
|
9411
9447
|
};
|
|
9412
|
-
/** @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. */
|
|
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. */
|
|
9413
9449
|
424: {
|
|
9414
9450
|
headers: {
|
|
9415
9451
|
[name: string]: unknown;
|
|
@@ -9420,7 +9456,7 @@ export interface paths {
|
|
|
9420
9456
|
ok: false;
|
|
9421
9457
|
provider: string;
|
|
9422
9458
|
/** @enum {string} */
|
|
9423
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9424
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. */
|
|
9425
9461
|
detail?: string;
|
|
9426
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. */
|
|
@@ -9434,6 +9470,8 @@ export interface paths {
|
|
|
9434
9470
|
alternative?: string;
|
|
9435
9471
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9436
9472
|
caveat?: string;
|
|
9473
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9474
|
+
expires_at?: string;
|
|
9437
9475
|
};
|
|
9438
9476
|
};
|
|
9439
9477
|
};
|
|
@@ -9448,7 +9486,7 @@ export interface paths {
|
|
|
9448
9486
|
ok: false;
|
|
9449
9487
|
provider: string;
|
|
9450
9488
|
/** @enum {string} */
|
|
9451
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9452
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. */
|
|
9453
9491
|
detail?: string;
|
|
9454
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. */
|
|
@@ -9462,6 +9500,8 @@ export interface paths {
|
|
|
9462
9500
|
alternative?: string;
|
|
9463
9501
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9464
9502
|
caveat?: string;
|
|
9503
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9504
|
+
expires_at?: string;
|
|
9465
9505
|
};
|
|
9466
9506
|
};
|
|
9467
9507
|
};
|
|
@@ -9476,7 +9516,7 @@ export interface paths {
|
|
|
9476
9516
|
ok: false;
|
|
9477
9517
|
provider: string;
|
|
9478
9518
|
/** @enum {string} */
|
|
9479
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9480
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. */
|
|
9481
9521
|
detail?: string;
|
|
9482
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. */
|
|
@@ -9490,6 +9530,8 @@ export interface paths {
|
|
|
9490
9530
|
alternative?: string;
|
|
9491
9531
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9492
9532
|
caveat?: string;
|
|
9533
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9534
|
+
expires_at?: string;
|
|
9493
9535
|
};
|
|
9494
9536
|
};
|
|
9495
9537
|
};
|
|
@@ -9504,7 +9546,7 @@ export interface paths {
|
|
|
9504
9546
|
ok: false;
|
|
9505
9547
|
provider: string;
|
|
9506
9548
|
/** @enum {string} */
|
|
9507
|
-
error: "server_unknown" | "verify_unsupported" | "not_connected" | "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";
|
|
9508
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. */
|
|
9509
9551
|
detail?: string;
|
|
9510
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. */
|
|
@@ -9518,6 +9560,8 @@ export interface paths {
|
|
|
9518
9560
|
alternative?: string;
|
|
9519
9561
|
/** @description Added only for a `cert` rail in the test environment, where the connect cannot be completed at all rather than merely being unfinished. */
|
|
9520
9562
|
caveat?: string;
|
|
9563
|
+
/** @description Present on `connection_expired` only: the ISO instant the connection's OAuth access token expired. */
|
|
9564
|
+
expires_at?: string;
|
|
9521
9565
|
};
|
|
9522
9566
|
};
|
|
9523
9567
|
};
|
|
@@ -12978,7 +13022,10 @@ export interface paths {
|
|
|
12978
13022
|
server_id: string;
|
|
12979
13023
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
12980
13024
|
auth_type: string;
|
|
12981
|
-
/**
|
|
13025
|
+
/**
|
|
13026
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13027
|
+
* @enum {string}
|
|
13028
|
+
*/
|
|
12982
13029
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
12983
13030
|
display_name: string | null;
|
|
12984
13031
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -13071,7 +13118,10 @@ export interface paths {
|
|
|
13071
13118
|
server_id: string;
|
|
13072
13119
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
13073
13120
|
auth_type: string;
|
|
13074
|
-
/**
|
|
13121
|
+
/**
|
|
13122
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13123
|
+
* @enum {string}
|
|
13124
|
+
*/
|
|
13075
13125
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
13076
13126
|
display_name: string | null;
|
|
13077
13127
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -13111,7 +13161,10 @@ export interface paths {
|
|
|
13111
13161
|
server_id: string;
|
|
13112
13162
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
13113
13163
|
auth_type: string;
|
|
13114
|
-
/**
|
|
13164
|
+
/**
|
|
13165
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13166
|
+
* @enum {string}
|
|
13167
|
+
*/
|
|
13115
13168
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
13116
13169
|
display_name: string | null;
|
|
13117
13170
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -13298,7 +13351,10 @@ export interface paths {
|
|
|
13298
13351
|
server_id: string;
|
|
13299
13352
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
13300
13353
|
auth_type: string;
|
|
13301
|
-
/**
|
|
13354
|
+
/**
|
|
13355
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13356
|
+
* @enum {string}
|
|
13357
|
+
*/
|
|
13302
13358
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
13303
13359
|
display_name: string | null;
|
|
13304
13360
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -13417,7 +13473,10 @@ export interface paths {
|
|
|
13417
13473
|
server_id: string;
|
|
13418
13474
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
13419
13475
|
auth_type: string;
|
|
13420
|
-
/**
|
|
13476
|
+
/**
|
|
13477
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13478
|
+
* @enum {string}
|
|
13479
|
+
*/
|
|
13421
13480
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
13422
13481
|
display_name: string | null;
|
|
13423
13482
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -13561,7 +13620,10 @@ export interface paths {
|
|
|
13561
13620
|
server_id: string;
|
|
13562
13621
|
/** @description Mirrors the catalog's `auth_type` at connect time: api_key, path_secret, cert, hmac_signed, jwt_ecdsa, two_header, oauth, cdp or none. Left open because the column is plain text. */
|
|
13563
13622
|
auth_type: string;
|
|
13564
|
-
/**
|
|
13623
|
+
/**
|
|
13624
|
+
* @description `expired` includes an OAuth connection whose access token passed `expires_at`: nothing refreshes it yet, calls through it answer `connection_expired`, and the fix is to reconnect. `?status=` filters on this same value.
|
|
13625
|
+
* @enum {string}
|
|
13626
|
+
*/
|
|
13565
13627
|
status: "pending" | "connected" | "revoked" | "expired";
|
|
13566
13628
|
display_name: string | null;
|
|
13567
13629
|
/** @description Provider metadata the OAuth callback wrote (scope, refresh ref) or the provisioning projection wrote (account_id). Always present; null for a key registered through POST /v1/connections, which never sets it. */
|
|
@@ -14831,6 +14893,8 @@ export interface paths {
|
|
|
14831
14893
|
* The cumulative cap is checked and CONSUMED under an advisory lock, and the wallet hold is taken inside that same lock. The lock is released before the provider call, so a slow provider does not serialize everyone else.
|
|
14832
14894
|
*
|
|
14833
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.
|
|
14896
|
+
*
|
|
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.
|
|
14834
14898
|
*/
|
|
14835
14899
|
post: {
|
|
14836
14900
|
parameters: {
|
|
@@ -14855,6 +14919,7 @@ export interface paths {
|
|
|
14855
14919
|
ted?: components["schemas"]["TedDestination"];
|
|
14856
14920
|
quote?: components["schemas"]["SpendQuote"];
|
|
14857
14921
|
actor?: components["schemas"]["PaymentActor"];
|
|
14922
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
14858
14923
|
};
|
|
14859
14924
|
};
|
|
14860
14925
|
};
|
|
@@ -14868,7 +14933,7 @@ export interface paths {
|
|
|
14868
14933
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
14869
14934
|
};
|
|
14870
14935
|
};
|
|
14871
|
-
/** @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. */
|
|
14872
14937
|
400: {
|
|
14873
14938
|
headers: {
|
|
14874
14939
|
[name: string]: unknown;
|
|
@@ -14877,7 +14942,7 @@ export interface paths {
|
|
|
14877
14942
|
"application/json": {
|
|
14878
14943
|
error: {
|
|
14879
14944
|
/** @enum {string} */
|
|
14880
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
14945
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
14881
14946
|
message: string;
|
|
14882
14947
|
details?: {
|
|
14883
14948
|
[key: string]: unknown;
|
|
@@ -14928,7 +14993,7 @@ export interface paths {
|
|
|
14928
14993
|
};
|
|
14929
14994
|
};
|
|
14930
14995
|
};
|
|
14931
|
-
/** @description Local state refuses. `psp_attempt_in_flight`: the same attempt is already in flight. `psp_attempt_uncertain`: an earlier attempt ended with an unknown outcome and this intent is PINNED to it, so present the same `attempt_id` again, never a new one. `psp_attempt_conflict`: the earlier attempt was already compensated. */
|
|
14996
|
+
/** @description Local state refuses. `psp_attempt_in_flight`: the same attempt is already in flight; retry the SAME `attempt_id` once it has answered, never a new one. `psp_attempt_uncertain`: an earlier attempt ended with an unknown outcome and this intent is PINNED to it, so present the same `attempt_id` again, never a new one. `psp_attempt_conflict`: the earlier attempt was already compensated. `attempt_id_conflict`: this `attempt_id` was already used for a different payment (`mismatched_fields` names what differs); nothing was held or sent. `attempt_id_unavailable`: another project of this organization holds this `attempt_id`; use a new one. */
|
|
14932
14997
|
409: {
|
|
14933
14998
|
headers: {
|
|
14934
14999
|
[name: string]: unknown;
|
|
@@ -14937,7 +15002,7 @@ export interface paths {
|
|
|
14937
15002
|
"application/json": {
|
|
14938
15003
|
error: {
|
|
14939
15004
|
/** @enum {string} */
|
|
14940
|
-
code: "psp_attempt_in_flight" | "psp_attempt_uncertain" | "psp_attempt_conflict";
|
|
15005
|
+
code: "psp_attempt_in_flight" | "psp_attempt_uncertain" | "psp_attempt_conflict" | "attempt_id_conflict" | "attempt_id_unavailable";
|
|
14941
15006
|
message: string;
|
|
14942
15007
|
details?: {
|
|
14943
15008
|
[key: string]: unknown;
|
|
@@ -15058,6 +15123,8 @@ export interface paths {
|
|
|
15058
15123
|
* 3. The destination must be NAMED in a signed list of the mandate, and a merchant-list wildcard `"*"` NEVER authorizes money out. Which list is accepted is mid-rollout, so read this one carefully: the target rule is `withdrawal_allowlist` alone, and while the rollout flag is off a destination named explicitly in the signed `merchant_allowlist` is ALSO accepted, with the stricter rule's refusal recorded rather than applied. Tolerance never widens what passes: a wildcard is refused on both paths, and a destination in neither list is refused with its own code. Build against `withdrawal_allowlist`: it is the list that keeps working when the flag turns on.
|
|
15059
15124
|
*
|
|
15060
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.
|
|
15126
|
+
*
|
|
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.
|
|
15061
15128
|
*/
|
|
15062
15129
|
post: {
|
|
15063
15130
|
parameters: {
|
|
@@ -15081,6 +15148,7 @@ export interface paths {
|
|
|
15081
15148
|
ted?: components["schemas"]["TedDestination"];
|
|
15082
15149
|
quote?: components["schemas"]["SpendQuote"];
|
|
15083
15150
|
actor?: components["schemas"]["PaymentActor"];
|
|
15151
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
15084
15152
|
};
|
|
15085
15153
|
};
|
|
15086
15154
|
};
|
|
@@ -15094,7 +15162,7 @@ export interface paths {
|
|
|
15094
15162
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
15095
15163
|
};
|
|
15096
15164
|
};
|
|
15097
|
-
/** @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. */
|
|
15098
15166
|
400: {
|
|
15099
15167
|
headers: {
|
|
15100
15168
|
[name: string]: unknown;
|
|
@@ -15103,7 +15171,7 @@ export interface paths {
|
|
|
15103
15171
|
"application/json": {
|
|
15104
15172
|
error: {
|
|
15105
15173
|
/** @enum {string} */
|
|
15106
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
15174
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
15107
15175
|
message: string;
|
|
15108
15176
|
details?: {
|
|
15109
15177
|
[key: string]: unknown;
|
|
@@ -15134,7 +15202,7 @@ export interface paths {
|
|
|
15134
15202
|
};
|
|
15135
15203
|
};
|
|
15136
15204
|
};
|
|
15137
|
-
/** @description Local state refuses, on the same
|
|
15205
|
+
/** @description Local state refuses, on the same five conditions as the by-id route. */
|
|
15138
15206
|
409: {
|
|
15139
15207
|
headers: {
|
|
15140
15208
|
[name: string]: unknown;
|
|
@@ -15143,7 +15211,7 @@ export interface paths {
|
|
|
15143
15211
|
"application/json": {
|
|
15144
15212
|
error: {
|
|
15145
15213
|
/** @enum {string} */
|
|
15146
|
-
code: "psp_attempt_in_flight" | "psp_attempt_uncertain" | "psp_attempt_conflict";
|
|
15214
|
+
code: "psp_attempt_in_flight" | "psp_attempt_uncertain" | "psp_attempt_conflict" | "attempt_id_conflict" | "attempt_id_unavailable";
|
|
15147
15215
|
message: string;
|
|
15148
15216
|
details?: {
|
|
15149
15217
|
[key: string]: unknown;
|
|
@@ -15238,6 +15306,8 @@ export interface paths {
|
|
|
15238
15306
|
* The outcome is the same object the sibling route returns, carried on the last event. A client that does not need to follow progress should use `/execute`: streaming does not make settlement faster, it makes it observable while it runs.
|
|
15239
15307
|
*
|
|
15240
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.
|
|
15309
|
+
*
|
|
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.
|
|
15241
15311
|
*/
|
|
15242
15312
|
post: {
|
|
15243
15313
|
parameters: {
|
|
@@ -15259,6 +15329,7 @@ export interface paths {
|
|
|
15259
15329
|
ted?: components["schemas"]["TedDestination"];
|
|
15260
15330
|
quote?: components["schemas"]["SpendQuote"];
|
|
15261
15331
|
actor?: components["schemas"]["PaymentActor"];
|
|
15332
|
+
approval?: components["schemas"]["SpendApproval"];
|
|
15262
15333
|
};
|
|
15263
15334
|
};
|
|
15264
15335
|
};
|
|
@@ -15272,7 +15343,7 @@ export interface paths {
|
|
|
15272
15343
|
"text/event-stream": string;
|
|
15273
15344
|
};
|
|
15274
15345
|
};
|
|
15275
|
-
/** @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. */
|
|
15276
15347
|
400: {
|
|
15277
15348
|
headers: {
|
|
15278
15349
|
[name: string]: unknown;
|
|
@@ -15281,7 +15352,7 @@ export interface paths {
|
|
|
15281
15352
|
"application/json": {
|
|
15282
15353
|
error: {
|
|
15283
15354
|
/** @enum {string} */
|
|
15284
|
-
code: "invalid_body" | "actor_consumer_mismatch";
|
|
15355
|
+
code: "invalid_body" | "invalid_approval_hash" | "invalid_receipt_timestamp" | "actor_consumer_mismatch" | "attempt_id_required";
|
|
15285
15356
|
message: string;
|
|
15286
15357
|
details?: {
|
|
15287
15358
|
[key: string]: unknown;
|
|
@@ -18075,7 +18146,10 @@ export interface paths {
|
|
|
18075
18146
|
nonce: string;
|
|
18076
18147
|
scope: string;
|
|
18077
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. */
|
|
18078
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;
|
|
18079
18153
|
};
|
|
18080
18154
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
18081
18155
|
quote: {
|
|
@@ -18087,6 +18161,15 @@ export interface paths {
|
|
|
18087
18161
|
sig: string | null;
|
|
18088
18162
|
at: string | null;
|
|
18089
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
|
+
};
|
|
18090
18173
|
payment: {
|
|
18091
18174
|
rail: string;
|
|
18092
18175
|
provider: string | null;
|
|
@@ -18121,7 +18204,20 @@ export interface paths {
|
|
|
18121
18204
|
nfe_chave: string | null;
|
|
18122
18205
|
at: string | null;
|
|
18123
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
|
+
*/
|
|
18124
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;
|
|
18125
18221
|
receipt_sig: string;
|
|
18126
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. */
|
|
18127
18223
|
receipt_sig_ed25519: string | null;
|
|
@@ -18198,7 +18294,10 @@ export interface paths {
|
|
|
18198
18294
|
nonce: string;
|
|
18199
18295
|
scope: string;
|
|
18200
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. */
|
|
18201
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;
|
|
18202
18301
|
};
|
|
18203
18302
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
18204
18303
|
quote: {
|
|
@@ -18210,6 +18309,15 @@ export interface paths {
|
|
|
18210
18309
|
sig: string | null;
|
|
18211
18310
|
at: string | null;
|
|
18212
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
|
+
};
|
|
18213
18321
|
payment: {
|
|
18214
18322
|
rail: string;
|
|
18215
18323
|
provider: string | null;
|
|
@@ -18244,7 +18352,20 @@ export interface paths {
|
|
|
18244
18352
|
nfe_chave: string | null;
|
|
18245
18353
|
at: string | null;
|
|
18246
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
|
+
*/
|
|
18247
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;
|
|
18248
18369
|
receipt_sig: string;
|
|
18249
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. */
|
|
18250
18371
|
receipt_sig_ed25519: string | null;
|
|
@@ -20144,6 +20265,10 @@ export interface paths {
|
|
|
20144
20265
|
/** @enum {string} */
|
|
20145
20266
|
kind: "order_confirmation" | "nfe" | "nfse" | "tracking" | "resource" | "merchant_ref" | "pix_e2e";
|
|
20146
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
|
+
*/
|
|
20147
20272
|
at?: string;
|
|
20148
20273
|
};
|
|
20149
20274
|
};
|
|
@@ -20176,7 +20301,10 @@ export interface paths {
|
|
|
20176
20301
|
nonce: string;
|
|
20177
20302
|
scope: string;
|
|
20178
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. */
|
|
20179
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;
|
|
20180
20308
|
};
|
|
20181
20309
|
/** @description Null when the receipt carries neither a seller nor a resource. */
|
|
20182
20310
|
quote: {
|
|
@@ -20188,6 +20316,15 @@ export interface paths {
|
|
|
20188
20316
|
sig: string | null;
|
|
20189
20317
|
at: string | null;
|
|
20190
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
|
+
};
|
|
20191
20328
|
payment: {
|
|
20192
20329
|
rail: string;
|
|
20193
20330
|
provider: string | null;
|
|
@@ -20222,7 +20359,20 @@ export interface paths {
|
|
|
20222
20359
|
nfe_chave: string | null;
|
|
20223
20360
|
at: string | null;
|
|
20224
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
|
+
*/
|
|
20225
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;
|
|
20226
20376
|
receipt_sig: string;
|
|
20227
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. */
|
|
20228
20378
|
receipt_sig_ed25519: string | null;
|
|
@@ -20236,7 +20386,7 @@ export interface paths {
|
|
|
20236
20386
|
};
|
|
20237
20387
|
};
|
|
20238
20388
|
};
|
|
20239
|
-
/** @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. */
|
|
20240
20390
|
400: {
|
|
20241
20391
|
headers: {
|
|
20242
20392
|
[name: string]: unknown;
|
|
@@ -20245,7 +20395,7 @@ export interface paths {
|
|
|
20245
20395
|
"application/json": {
|
|
20246
20396
|
error: {
|
|
20247
20397
|
/** @enum {string} */
|
|
20248
|
-
code: "invalid_body";
|
|
20398
|
+
code: "invalid_body" | "invalid_receipt_timestamp";
|
|
20249
20399
|
message: string;
|
|
20250
20400
|
details?: {
|
|
20251
20401
|
[key: string]: unknown;
|
|
@@ -21008,7 +21158,11 @@ export interface paths {
|
|
|
21008
21158
|
};
|
|
21009
21159
|
};
|
|
21010
21160
|
};
|
|
21011
|
-
/**
|
|
21161
|
+
/**
|
|
21162
|
+
* @description `illegal_transition`: the consent's current status does not permit authorisation. `details.from` and `details.to` carry the pair.
|
|
21163
|
+
*
|
|
21164
|
+
* `consent_expired`: the consent is `pending` and its validity window (`details.expires_at`) has elapsed. TERMINAL: the grant can no longer be authorised. The status stays `pending` on the row and is read as expired by this route, so it still occupies this project's one open consent for the consumer at this bank: revoke it, then initiate a new consent. Another project is not blocked by it.
|
|
21165
|
+
*/
|
|
21012
21166
|
409: {
|
|
21013
21167
|
headers: {
|
|
21014
21168
|
[name: string]: unknown;
|
|
@@ -21017,7 +21171,27 @@ export interface paths {
|
|
|
21017
21171
|
"application/json": {
|
|
21018
21172
|
error: {
|
|
21019
21173
|
/** @enum {string} */
|
|
21020
|
-
code: "illegal_transition";
|
|
21174
|
+
code: "illegal_transition" | "consent_expired";
|
|
21175
|
+
message: string;
|
|
21176
|
+
details?: {
|
|
21177
|
+
[key: string]: unknown;
|
|
21178
|
+
};
|
|
21179
|
+
};
|
|
21180
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21181
|
+
request_id: string | null;
|
|
21182
|
+
};
|
|
21183
|
+
};
|
|
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";
|
|
21021
21195
|
message: string;
|
|
21022
21196
|
details?: {
|
|
21023
21197
|
[key: string]: unknown;
|
|
@@ -21068,6 +21242,26 @@ export interface paths {
|
|
|
21068
21242
|
};
|
|
21069
21243
|
};
|
|
21070
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
|
+
};
|
|
21071
21265
|
};
|
|
21072
21266
|
};
|
|
21073
21267
|
delete?: never;
|
|
@@ -21174,7 +21368,13 @@ export interface paths {
|
|
|
21174
21368
|
};
|
|
21175
21369
|
};
|
|
21176
21370
|
};
|
|
21177
|
-
/**
|
|
21371
|
+
/**
|
|
21372
|
+
* @description `consent_not_authorised`: the consent is not in `authorised`. `details.status` carries what it is.
|
|
21373
|
+
*
|
|
21374
|
+
* `consent_expired`: the consent's validity window (`details.expires_at`) has elapsed. The consent is moved to `expired` by this same call and nothing is fetched. TERMINAL: initiate a new consent.
|
|
21375
|
+
*
|
|
21376
|
+
* `consent_token_expired`: the consent is still valid but its access token (`details.token_expires_at`) has expired. NOT terminal: the consent stays `authorised`, because the grant is alive at the bank and the token is renewable. Nothing was fetched; do not initiate a new consent.
|
|
21377
|
+
*/
|
|
21178
21378
|
409: {
|
|
21179
21379
|
headers: {
|
|
21180
21380
|
[name: string]: unknown;
|
|
@@ -21183,7 +21383,27 @@ export interface paths {
|
|
|
21183
21383
|
"application/json": {
|
|
21184
21384
|
error: {
|
|
21185
21385
|
/** @enum {string} */
|
|
21186
|
-
code: "consent_not_authorised";
|
|
21386
|
+
code: "consent_not_authorised" | "consent_expired" | "consent_token_expired";
|
|
21387
|
+
message: string;
|
|
21388
|
+
details?: {
|
|
21389
|
+
[key: string]: unknown;
|
|
21390
|
+
};
|
|
21391
|
+
};
|
|
21392
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
21393
|
+
request_id: string | null;
|
|
21394
|
+
};
|
|
21395
|
+
};
|
|
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";
|
|
21187
21407
|
message: string;
|
|
21188
21408
|
details?: {
|
|
21189
21409
|
[key: string]: unknown;
|
|
@@ -21234,6 +21454,26 @@ export interface paths {
|
|
|
21234
21454
|
};
|
|
21235
21455
|
};
|
|
21236
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
|
+
};
|
|
21237
21477
|
};
|
|
21238
21478
|
};
|
|
21239
21479
|
delete?: never;
|
|
@@ -21966,6 +22206,26 @@ export interface paths {
|
|
|
21966
22206
|
};
|
|
21967
22207
|
};
|
|
21968
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
|
+
};
|
|
21969
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. */
|
|
21970
22230
|
500: {
|
|
21971
22231
|
headers: {
|
|
@@ -22006,7 +22266,11 @@ export interface paths {
|
|
|
22006
22266
|
};
|
|
22007
22267
|
};
|
|
22008
22268
|
};
|
|
22009
|
-
/**
|
|
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
|
+
*/
|
|
22010
22274
|
503: {
|
|
22011
22275
|
headers: {
|
|
22012
22276
|
[name: string]: unknown;
|
|
@@ -22015,7 +22279,7 @@ export interface paths {
|
|
|
22015
22279
|
"application/json": {
|
|
22016
22280
|
error: {
|
|
22017
22281
|
/** @enum {string} */
|
|
22018
|
-
code: "consent_lock_timeout";
|
|
22282
|
+
code: "consent_lock_timeout" | "ofb_adapter_unavailable";
|
|
22019
22283
|
message: string;
|
|
22020
22284
|
details?: {
|
|
22021
22285
|
[key: string]: unknown;
|
|
@@ -22150,7 +22414,11 @@ export interface paths {
|
|
|
22150
22414
|
};
|
|
22151
22415
|
};
|
|
22152
22416
|
};
|
|
22153
|
-
/**
|
|
22417
|
+
/**
|
|
22418
|
+
* @description `illegal_transition`: the consent's current status does not permit authorisation. `details.from` and `details.to` carry the pair.
|
|
22419
|
+
*
|
|
22420
|
+
* `consent_expired`: the consent is `pending` and its validity window (`details.expires_at`) has elapsed. TERMINAL: the grant can no longer be authorised. The status stays `pending` on the row and is read as expired by this route, so it still occupies this project's one open consent for the consumer at this bank: revoke it, then initiate a new consent. Another project is not blocked by it.
|
|
22421
|
+
*/
|
|
22154
22422
|
409: {
|
|
22155
22423
|
headers: {
|
|
22156
22424
|
[name: string]: unknown;
|
|
@@ -22159,7 +22427,27 @@ export interface paths {
|
|
|
22159
22427
|
"application/json": {
|
|
22160
22428
|
error: {
|
|
22161
22429
|
/** @enum {string} */
|
|
22162
|
-
code: "illegal_transition";
|
|
22430
|
+
code: "illegal_transition" | "consent_expired";
|
|
22431
|
+
message: string;
|
|
22432
|
+
details?: {
|
|
22433
|
+
[key: string]: unknown;
|
|
22434
|
+
};
|
|
22435
|
+
};
|
|
22436
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22437
|
+
request_id: string | null;
|
|
22438
|
+
};
|
|
22439
|
+
};
|
|
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";
|
|
22163
22451
|
message: string;
|
|
22164
22452
|
details?: {
|
|
22165
22453
|
[key: string]: unknown;
|
|
@@ -22210,6 +22498,26 @@ export interface paths {
|
|
|
22210
22498
|
};
|
|
22211
22499
|
};
|
|
22212
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
|
+
};
|
|
22213
22521
|
};
|
|
22214
22522
|
};
|
|
22215
22523
|
delete?: never;
|
|
@@ -22311,7 +22619,13 @@ export interface paths {
|
|
|
22311
22619
|
};
|
|
22312
22620
|
};
|
|
22313
22621
|
};
|
|
22314
|
-
/**
|
|
22622
|
+
/**
|
|
22623
|
+
* @description `consent_not_authorised`: the consent is not in `authorised`. `details.status` carries what it is.
|
|
22624
|
+
*
|
|
22625
|
+
* `consent_expired`: the consent's validity window (`details.expires_at`) has elapsed. The consent is moved to `expired` by this same call and nothing is fetched. TERMINAL: initiate a new consent.
|
|
22626
|
+
*
|
|
22627
|
+
* `consent_token_expired`: the consent is still valid but its access token (`details.token_expires_at`) has expired. NOT terminal: the consent stays `authorised`, because the grant is alive at the bank and the token is renewable. Nothing was fetched; do not initiate a new consent.
|
|
22628
|
+
*/
|
|
22315
22629
|
409: {
|
|
22316
22630
|
headers: {
|
|
22317
22631
|
[name: string]: unknown;
|
|
@@ -22320,7 +22634,27 @@ export interface paths {
|
|
|
22320
22634
|
"application/json": {
|
|
22321
22635
|
error: {
|
|
22322
22636
|
/** @enum {string} */
|
|
22323
|
-
code: "consent_not_authorised";
|
|
22637
|
+
code: "consent_not_authorised" | "consent_expired" | "consent_token_expired";
|
|
22638
|
+
message: string;
|
|
22639
|
+
details?: {
|
|
22640
|
+
[key: string]: unknown;
|
|
22641
|
+
};
|
|
22642
|
+
};
|
|
22643
|
+
/** @description Echoes the `X-Request-Id` header when the request carried one. */
|
|
22644
|
+
request_id: string | null;
|
|
22645
|
+
};
|
|
22646
|
+
};
|
|
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";
|
|
22324
22658
|
message: string;
|
|
22325
22659
|
details?: {
|
|
22326
22660
|
[key: string]: unknown;
|
|
@@ -22371,6 +22705,26 @@ export interface paths {
|
|
|
22371
22705
|
};
|
|
22372
22706
|
};
|
|
22373
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
|
+
};
|
|
22374
22728
|
};
|
|
22375
22729
|
};
|
|
22376
22730
|
delete?: never;
|
|
@@ -23597,6 +23951,8 @@ export interface paths {
|
|
|
23597
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.
|
|
23598
23952
|
*
|
|
23599
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.
|
|
23600
23956
|
*/
|
|
23601
23957
|
get: {
|
|
23602
23958
|
parameters: {
|
|
@@ -23628,8 +23984,8 @@ export interface paths {
|
|
|
23628
23984
|
matched_rule_id: string;
|
|
23629
23985
|
matched_rule_name: string;
|
|
23630
23986
|
tool_name: string;
|
|
23631
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23632
|
-
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?: {
|
|
23633
23989
|
[key: string]: unknown;
|
|
23634
23990
|
};
|
|
23635
23991
|
/**
|
|
@@ -23704,7 +24060,7 @@ export interface paths {
|
|
|
23704
24060
|
* @deprecated
|
|
23705
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.
|
|
23706
24062
|
*
|
|
23707
|
-
* `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.
|
|
23708
24064
|
*/
|
|
23709
24065
|
post: {
|
|
23710
24066
|
parameters: {
|
|
@@ -23741,8 +24097,8 @@ export interface paths {
|
|
|
23741
24097
|
matched_rule_id: string;
|
|
23742
24098
|
matched_rule_name: string;
|
|
23743
24099
|
tool_name: string;
|
|
23744
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23745
|
-
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?: {
|
|
23746
24102
|
[key: string]: unknown;
|
|
23747
24103
|
};
|
|
23748
24104
|
/**
|
|
@@ -23783,7 +24139,7 @@ export interface paths {
|
|
|
23783
24139
|
};
|
|
23784
24140
|
};
|
|
23785
24141
|
};
|
|
23786
|
-
/** @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. */
|
|
23787
24143
|
403: {
|
|
23788
24144
|
headers: {
|
|
23789
24145
|
[name: string]: unknown;
|
|
@@ -23827,8 +24183,8 @@ export interface paths {
|
|
|
23827
24183
|
matched_rule_id: string;
|
|
23828
24184
|
matched_rule_name: string;
|
|
23829
24185
|
tool_name: string;
|
|
23830
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23831
|
-
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?: {
|
|
23832
24188
|
[key: string]: unknown;
|
|
23833
24189
|
};
|
|
23834
24190
|
/**
|
|
@@ -23871,8 +24227,8 @@ export interface paths {
|
|
|
23871
24227
|
matched_rule_id: string;
|
|
23872
24228
|
matched_rule_name: string;
|
|
23873
24229
|
tool_name: string;
|
|
23874
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23875
|
-
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?: {
|
|
23876
24232
|
[key: string]: unknown;
|
|
23877
24233
|
};
|
|
23878
24234
|
/**
|
|
@@ -23942,7 +24298,7 @@ export interface paths {
|
|
|
23942
24298
|
* @deprecated
|
|
23943
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.
|
|
23944
24300
|
*
|
|
23945
|
-
* 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.
|
|
23946
24302
|
*
|
|
23947
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.
|
|
23948
24304
|
*/
|
|
@@ -23973,8 +24329,8 @@ export interface paths {
|
|
|
23973
24329
|
matched_rule_id: string;
|
|
23974
24330
|
matched_rule_name: string;
|
|
23975
24331
|
tool_name: string;
|
|
23976
|
-
/** @description The tool arguments the rule held for review, verbatim. */
|
|
23977
|
-
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?: {
|
|
23978
24334
|
[key: string]: unknown;
|
|
23979
24335
|
};
|
|
23980
24336
|
/**
|
|
@@ -24032,7 +24388,7 @@ export interface paths {
|
|
|
24032
24388
|
* @deprecated
|
|
24033
24389
|
* @description DEPRECATED alias of `GET /v1/approvals/health` (ent#979), kept for two releases. Same handler, same `approvals:read` scope.
|
|
24034
24390
|
*
|
|
24035
|
-
* 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.
|
|
24036
24392
|
*
|
|
24037
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.
|
|
24038
24394
|
*
|
|
@@ -25801,7 +26157,7 @@ export interface paths {
|
|
|
25801
26157
|
};
|
|
25802
26158
|
};
|
|
25803
26159
|
};
|
|
25804
|
-
/** @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. */
|
|
25805
26161
|
403: {
|
|
25806
26162
|
headers: {
|
|
25807
26163
|
[name: string]: unknown;
|
|
@@ -29860,7 +30216,7 @@ export interface paths {
|
|
|
29860
30216
|
* Complete the review of a payable
|
|
29861
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.
|
|
29862
30218
|
*
|
|
29863
|
-
* **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.
|
|
29864
30220
|
*
|
|
29865
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.
|
|
29866
30222
|
*
|
|
@@ -30432,7 +30788,7 @@ export interface paths {
|
|
|
30432
30788
|
};
|
|
30433
30789
|
};
|
|
30434
30790
|
};
|
|
30435
|
-
/** @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. */
|
|
30436
30792
|
403: {
|
|
30437
30793
|
headers: {
|
|
30438
30794
|
[name: string]: unknown;
|
|
@@ -33870,7 +34226,7 @@ export interface paths {
|
|
|
33870
34226
|
};
|
|
33871
34227
|
};
|
|
33872
34228
|
};
|
|
33873
|
-
/** @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). */
|
|
33874
34230
|
424: {
|
|
33875
34231
|
headers: {
|
|
33876
34232
|
[name: string]: unknown;
|
|
@@ -33883,6 +34239,12 @@ export interface paths {
|
|
|
33883
34239
|
reason: "server_unknown" | "not_connected" | "endpoint_missing";
|
|
33884
34240
|
server: string;
|
|
33885
34241
|
message: string;
|
|
34242
|
+
} | {
|
|
34243
|
+
/** @enum {string} */
|
|
34244
|
+
error: "shared_sandbox_live_project_refused";
|
|
34245
|
+
reason: string;
|
|
34246
|
+
server: string;
|
|
34247
|
+
message: string;
|
|
33886
34248
|
};
|
|
33887
34249
|
};
|
|
33888
34250
|
};
|
|
@@ -36578,6 +36940,10 @@ export interface components {
|
|
|
36578
36940
|
} | null;
|
|
36579
36941
|
/** @description The lifecycle steps, in order, each with a timestamp and an outcome. */
|
|
36580
36942
|
audit: unknown[];
|
|
36943
|
+
/** @description The attempt this payment settled under: the `attempt_id` sent, or the fresh one minted when none was. Presenting it again reads this outcome instead of paying again. */
|
|
36944
|
+
attempt_id: string;
|
|
36945
|
+
/** @description True when this `attempt_id` had already settled and this is its recorded outcome, answered again: every other field is the ORIGINAL response, verbatim, and nothing was sent, held, sealed or published by this call. False on the call that settled it. */
|
|
36946
|
+
idempotent_replay: boolean;
|
|
36581
36947
|
};
|
|
36582
36948
|
/** @description The destination of a TED, the Brazilian same-day bank wire. Present this object on a spend to send a wire instead of a Pix: its presence is what switches the rail, and what makes the three TED requirements on those operations bind. Money leaves the consumer's own sub-account, never a pooled one. */
|
|
36583
36949
|
TedDestination: {
|
|
@@ -36611,6 +36977,10 @@ export interface components {
|
|
|
36611
36977
|
price_minor: number;
|
|
36612
36978
|
payee: string;
|
|
36613
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
|
+
*/
|
|
36614
36984
|
at?: string;
|
|
36615
36985
|
};
|
|
36616
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. */
|
|
@@ -36629,6 +36999,17 @@ export interface components {
|
|
|
36629
36999
|
/** @description Where the person acted from: `whatsapp`, `dashboard`, `cli`. */
|
|
36630
37000
|
channel?: string;
|
|
36631
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
|
+
};
|
|
36632
37013
|
};
|
|
36633
37014
|
responses: never;
|
|
36634
37015
|
parameters: never;
|