# Protocol standards

The API follows a set of HTTP API standards and supports
[idempotency](https://developers.google.com/pay/e-wallets-v1/guides/connectivity/protocol-standards#request_idempotency) to facilitate a more robust
integration.

### Google hosted URLs

The documentation for each Google-hosted method provides a base URL, which
includes the method name and major version number. The complete URL is created
by adding the caller's [Payment Integrator Account ID](https://developers.google.com/pay/e-wallets-v1/reference/glossary#payment_integrator_account_id) to the
end. For example, the documentation for the [Google-hosted echo method](https://developers.google.com/pay/e-wallets-v1/google-e-wallets-api/echo)
specifies the URL:
`https://vgw.googleapis.com/gsp/e-wallets-v1/echo`

If the caller's Payment Integrator Account ID is `INTEGRATOR_1`, they would add
that to the end of the URL to form:
`https://vgw.googleapis.com/gsp/e-wallets-v1/echo/INTEGRATOR_1`

> [!NOTE]
> **Note:** The endpoint documentation page for the specific method you are implementing will have the most accurate URL for your case.

### Partner hosted URLs

The documentation for each partner hosted API method provides a base URL, which
includes the method name and major version number. You should not include the
[Payment Integrator Account ID (`PIAID`)](https://developers.google.com/pay/e-wallets-v1/reference/glossary#payment_integrator_account_id)
in the URLs you host.

## Sandbox and production environments

Google hosts e-Wallets APIs in both sandbox (for development and
testing purposes) and production. Requests in the Google sandbox environment
do not result in any real world financial liability. The sandbox and
production environments are completely separate and do not share keys or
transaction information.

Google expects that your sandbox is consistently available since we'll use the
sandbox to first test changes and new features.

### Google's sandbox base path

`https://vgw.sandbox.google.com/gsp/`

> [!NOTE]
> **Note:** If your integration is already launched and calls the `https://billpaynotification.sandbox.googleapis.com` host, you may continue to do so. New integrations should call the 'vgw.sandbox.google.com' host.

### Google's Production base path

`https://vgw.googleapis.com/gsp/`

> [!NOTE]
> **Note:** If your integration is already launched and calls the `https://billpaynotification.googleapis.com` host, you may continue to do so. New integrations should call the 'vgw.googleapis.com' host.

This guide will use the production endpoints.

## Content type and encoding

Message payloads that use PGP encryption must use the content type `application/octet-stream; charset=utf-8`. PGP request bodies must be sent using base64url encoding, as defined in [rfc4648 §5](https://tools.ietf.org/html/rfc4648#section-5). Message payloads that use JWE encryption must use the content type `application/jose; charset=utf-8`. The Compact Serialization option supported by JWE/JWS handles the encoding for the final request body.

## HTTP status codes

e-Wallets APIs are designed to return an HTTP `200` status code
for all requests that can be processed by the server. This includes both
successful and declined requests from the perspective of business or
application logic. Requests that cannot be processed should not result in an
HTTP `200` status code since they represent an error between Google and the
partner. Instead, the API response should use the appropriate HTTP status
codes below with an optional `ErrorResponse` object.

| HTTP Errors And Reasons ||
|---|---|
| 400 | `BAD REQUEST` Client specified an invalid argument. This can also be returned if the operation was rejected because the system is not in a state required for the operation's execution. Use this if retries of the request cannot succeed until the system state has been explicitly fixed. For example, if a refund request fails because it references a capture that does not exist, retrying will not succeed until the capture exists in the integrators system. > [!NOTE] > **Note:** that BAD_REQUEST (400) must not be used for situations where an appropriate application error is available. For example, incorrect currencies should return `ACCOUNT_DOES_NOT_SUPPORT_CURRENCY` with code 200 if the standard response has that field or enum. |
| 401 | `UNAUTHORIZED` The request does not have valid authentication credentials for the operation. For example, invalid signatures or unknown signatures should return 401. |
| 403 | `FORBIDDEN / PERMISSION DENIED` The caller does not have permission to execute the specified operation. |
| 404 | `NOT FOUND` Some requested entity such as payment or user was not found. |
| 409 | `CONFLICT / ABORTED` The operation was aborted, typically due to a concurrency issue like sequencer-check failures, transaction aborts, etc. |
| 412 | `PRECONDITION FAILED` This code should be used in situations where an idempotency key is being reused with different parameters. |
| 429 | `RESOURCE EXHAUSTED / TOO MANY REQUESTS` Some system resource has exhausted. |
| 499 | `CANCELLED` The operation was cancelled (typically by the caller). |
| 500 | `INTERNAL ERROR` Internal errors. This means some invariants expected by underlying system has been broken. |
| 501 | `UNIMPLEMENTED` Operation is not implemented, supported or enabled in this service. |
| 503 | `UNAVAILABLE` The service is currently unavailable. This is a most likely a transient condition and may be corrected by retrying. |
| 504 | `GATEWAY TIMEOUT / DEADLINE EXCEEDED` Deadline expired before operation could complete. For operations that change the state of the system, this error may be returned even if the operation has completed successfully. For example, a successful response from a server could have been delayed long enough for the deadline to expire. |

## Request idempotency

Request idempotency is a central strategy used in the e-Wallets
APIs used to ensure that system interactions between Google and partners are
robust and fault tolerant. Idempotent requests are requests that can
potentially be sent multiple times but have the same effect as a single request.
This strategy facilitates eventual consistency between systems by making
retries safe, allowing our systems to coalesce into agreement on the
state of the resource.

Our API leverages idempotency to:

- reduce reconciliation issues by making all actions easily traceable and auditable.
- prevent race conditions by ensuring that multiple identical requests from the same client do not result in a different final state.
- minimize state by allowing requests to be understood in isolation, allowing for improved performance and throughput by removing server load caused by retention of data.
- avoid the need for additional fields to indicate if a request is a retry

> [!NOTE]
> **Note:** Error results must never be cached or idempotently returned. And, automated retries for errors must use an exponential backoff strategy.

### Examples

#### Example 1: Connectivity lost before response received

Scenario:

1. Google sends a request to the integrator.
2. The integrator server receives this request and processes it successfully.
3. Google's server loses power prior to receiving the response in step #2.
4. Google's server power is restored and the same request is sent with all the same parameters (same request ID and request details but updated `requestTimestamp`) to the integrator's server.

Outcome:

In this case the integrator server must reply with the same reply given at
step #2 since all the parameters, except for `responseTimestamp`, are the same.
The side-effect only occurs once, at step 2. Step 4 has no side-effect.

#### Example 2: Request sent to a server undergoing maintenance

Scenario:

1. Integrator server's database is down for maintenance.
2. Google sends a request to the integrator.
3. Integrator correctly returns `UNAVAILABLE` status code.
4. Google's server receives the response and schedules a retry.
5. Integrator server's database comes back online.
6. Google resends the request from step #2 (same request ID and request details but updated `requestTimestamp`). Note that the request IDs for both requests should be the same.
7. Integrator server receives request and returns an OK status code along with full response.

Outcome:

In this case the integrator server must process the request in step #7 and not
return HTTP `503` (`UNAVAILABLE`). Instead, the integrator server should fully
process the request and return OK with appropriate messaging. Note that while
the system is `UNAVAILABLE` Google may make repeated requests similar to
step #2. Each request should result in a message similar to step #3.
Eventually, step #6 and step #7 will occur.

#### Example 3: Retried message does not match initial message due to recovery error

Scenario:

1. Google sends a request to the integrator.
2. The integrator server receives this request and processes it successfully.
3. Google's server loses power prior to receiving the response in step #2.
4. Google's server power is restored and attempts to send the same request but unfortunately some of the parameters are different.

Outcome:

In this case the integrator server should reply with an HTTP `412`
(`PRECONDITION FAILED`) error code which denotes to Google that there is an
error in this system.