Skip to content

gRPC WhatsApp API#

gRPC WhatsApp API β€” a Protobuf definition of every GREEN-API service method, from which a ready-to-use gRPC client is generated for the language you need: Go, Python, Java, C++, C#, JS/TS.

gRPC clients by language#

  • gRPC client in Go β€” installation, connecting and checking the connection, file upload, getting a QR code

  • gRPC client in Python β€” installation, connecting and checking the connection, file upload, getting a QR code

gRPC contract structure of the WhatsApp API#

The contract is a set of .proto files that define every method of the GREEN-API service, along with their request and response types. A ready-to-use gRPC client is generated from the contract, so method calls, serialization and type checking are not written by hand. To use the API, you need to obtain apiTokenInstance and idInstance in your personal account. For testing purposes we recommend the free "Developer" plan.

API#

The REST API documentation is available at this link. The gRPC contract contains the corresponding methods, so the description of their purpose and parameters also applies to the gRPC API.

In the .proto files of the services, each method has a comment with a link to its documentation. This lets you open the method description directly from the code editor.

Package structure#

Methods are grouped by domain. Each domain has its own directory in proto/greenapi/.

Directory Description
type/v1/ Shared types: File, Contact, message content variants, enums β€” reused across all the domains below
instance/v1/ Instance setup and authorization, getting the QR code/phone number and the instance state
message/v1/ Sending, editing and deleting messages; chat history; outgoing send queue
contact/v1/ Working with contacts: adding, editing, deleting, finding a contact and getting an avatar
chat/v1/ Working with chats: getting the list, archiving, muting, the "typing" status, read marks
group/v1/ Group chat management
status/v1/ Working with WhatsApp statuses (stories)
notification/v1/ Receiving notifications via webhook/long polling and working with the notification queue
call/v1/ History of incoming and outgoing calls

Each domain is versioned independently: v1 refers to the package, not to the whole contract. That is why a change in one domain does not require bumping the version in all the others.

A single message format#

Message content is described in one place β€” in type/v1/message_payload.proto. The MessageData type uses oneof and combines all supported message content types.

MessageData is used both in HistoryMessage from message/v1 to represent messages from the chat history and in MessageNotification from notification/v1 for notifications received via webhook and long polling. Thanks to the single format, the same message can be handled by the same code regardless of its source β€” the chat history or the notification stream.

Authorization in the gRPC API#

To send messages and call other GREEN-API methods, the instance must be authorized in WhatsApp. You can authorize the instance in your personal account by scanning a QR code in the WhatsApp application on your phone, or programmatically β€” with the ScanQrCode method.

In the REST API, idInstance and apiTokenInstance are passed as part of the request URL. In gRPC, this data is passed in the metadata of each call:

Metadata key Value
x-instance-id idInstance
authorization Bearer <apiTokenInstance>

Both values are sent with every call: the connection itself does not hold the authorization.

You can obtain idInstance and apiTokenInstance in your personal account after creating an instance.

If the metadata is not passed or the token is invalid, the call ends with the gRPC status Unauthenticated. For the list of errors common to all methods, see gRPC API error codes.

The metadata authorizes the instance, but not the account: the WhatsApp account itself must be in an authorized state, otherwise the methods will return FailedPrecondition.

Examples:

Checking the connection#

Before making working calls, it is recommended to check the connection to the gRPC server and the state of the instance. To do this, you can use the GetStateInstance method of the InstanceService service, which returns the current state of the instance and does not change it.

rpc GetStateInstance(GetStateInstanceRequest) returns (GetStateInstanceResponse);

GetStateInstanceRequest has no parameters. The response returns the state_instance field with a value of the InstanceState enumeration from the type/v1 package.

If the call ends with the gRPC OK status, the connection to the server and authorization were successful. The state_instance value lets you determine the current state of the instance and whether it is ready to work.

Result Description
INSTANCE_STATE_AUTHORIZED The instance is authorized and ready to work.
INSTANCE_STATE_NOT_AUTHORIZED The instance is not authorized in WhatsApp. Scan the QR code in your personal account or get it using the ScanQrCode method.
INSTANCE_STATE_STARTING The instance is starting. Wait and check the state again.
INSTANCE_STATE_BLOCKED, INSTANCE_STATE_SUSPENDED The instance operation is restricted. For details, see the description of the GetStateInstance method.
Unauthenticated error Authorization data was not passed, or idInstance / apiTokenInstance is incorrect. Check the values in your personal account.
Unavailable error Could not connect to the gRPC server. Check the server address. It must be specified in the grpc.green-api.com:443 format, without the https:// scheme.

Examples:

Streaming calls in the gRPC API#

Most gRPC API methods are unary: one request β€” one response. The exception is three streaming methods:

rpc UploadFile(stream UploadFileRequest) returns (UploadFileResponse);
rpc SendFileByUpload(stream SendFileByUploadRequest) returns (SendFileByUploadResponse);
rpc ScanQrCode(ScanQrCodeRequest) returns (stream ScanQrCodeResponse);

UploadFile and SendFileByUpload use a client stream: the file is sent in parts as a sequence of chunks rather than as one large message. ScanQrCode uses a server stream and is described separately in Getting a QR code over gRPC.

Binary fields#

Binary data in the contract β€” for example, qr_png, avatar_image, jpeg_thumbnail and File.file β€” is described by the bytes type. In native gRPC, such fields are sent as binary data, without conversion to Base64.

With the JSON representation, the behavior is different: according to the Protocol Buffers to JSON mapping rules, bytes fields are encoded in Base64. Therefore grpc-web, grpc-gateway and protojson represent such values in JSON as Base64 strings.

Thus, with native gRPC, binary data is sent directly in binary form, and with JSON interaction β€” as a Base64 string. The Base64 representation increases the data size by about 33%.

The upload contract#

Both upload methods use the following data transfer order:

  1. The first message of the stream contains UploadFileMetadata with the file_name and content_type fields. The metadata is sent once, at the start of the stream.
  2. All subsequent messages contain a chunk with the next part of the file. The messages are sent sequentially, and gRPC preserves their order within a single stream, so there is no need to pass additional indices or offsets for the chunks.
  3. After sending the last chunk, the client finishes sending messages (half-close). This tells the server that the file has been transferred in full. The server then processes the received data and returns a single UploadFileResponse containing url_file.

A half-close only ends the sending of data from the client side within the current RPC call and does not close the gRPC connection. The server can still send a response within the same call. Other RPC calls can keep running over the same connection independently.

Chunk size#

The recommended chunk size is from 32 to 256 KB. 64 KB is recommended as the default value. With smaller chunks, the overhead of sending individual messages can reduce efficiency, and with chunks that are too large, a further increase in chunk size usually gives no noticeable speed gain due to HTTP/2 flow control limits.

The size of a single chunk must not exceed 1 MB. If this value is exceeded, the call ends with the ResourceExhausted status. The server rejects the message before processing its contents. Only the current RPC call ends, and the gRPC connection stays open.

After the error, the upload must be repeated with a smaller chunk size. The data received within the failed call is not saved, and no url_file is generated.

Chunks do not have to be of the same size. The last chunk is usually smaller than the rest. The client can send data sequentially as it reads it from a file or a socket.

Interrupted uploads#

The server distinguishes a proper completion of an upload (half-close) from its interruption, for example when the call is cancelled, the deadline expires or the connection breaks. If an upload is interrupted, all data received within the current call is discarded.

Resuming an interrupted upload is not supported. A repeated upload must start from the beginning. No additional cleanup of partially uploaded data is required on the client side.

grpc-web limitation#

gRPC-Web does not support client streaming calls. Therefore the UploadFile and SendFileByUpload methods, which use a client stream, cannot be called through the generated gRPC-Web client for JavaScript/TypeScript.

Server streaming calls are supported in gRPC-Web, so this limitation does not apply to the ScanQrCode method.

Examples:

Getting a QR code over gRPC#

ScanQrCode is the gRPC counterpart of the GREEN-API WebSocket method for getting a QR code. The method uses a server stream: the server sends a ScanQrCodeResponse every time a new QR code is available, and ends the stream once the authorization attempt is over.

rpc ScanQrCode(ScanQrCodeRequest) returns (stream ScanQrCodeResponse);

The instance must be in the unauthorized state. Only one active ScanQrCode call is allowed per instance at a time; a parallel call will be rejected.

Information about a successful authorization is not sent through the ScanQrCode stream. The instance state change arrives as a separate stateInstanceChanged notification in the notification stream, after which the ScanQrCode stream ends.

To stop getting the QR code earlier, the client must cancel the current RPC call.

Statuses#

Every message contains a status field, which defines the response type and the contents of the other fields.

Status Description
QR_CODE_STATUS_QR_CODE The qr_png field contains the binary data of the QR code PNG image. To display it in a browser, you can convert it to Base64 and use it, for example, in data:image/png;base64,.... A new QR code is sent after the previous one expires.
QR_CODE_STATUS_PASSKEY_REQUIRED Authorization requires a passkey instead of scanning a QR code.
QR_CODE_STATUS_ALREADY_LOGGED The instance is already authorized. You must call Logout before getting a QR code again.

Call errors#

The WebSocket messages error and timeout have no direct counterparts in the ScanQrCode stream. In gRPC, such situations end the RPC call with the corresponding status.

The FailedPrecondition status is returned if the instance is not ready to perform the operation, for example when it is in the not ready or Instance starting state, or the logout is in progress (is in the logout process).

The DeadlineExceeded status is returned if the QR code was not scanned within about 100 seconds.

An additional description of the error is passed in the gRPC status text, so there is no separate message field in the response.

Examples:

gRPC API error codes#

A successful call ends with the gRPC status OK (code = 0) and returns the response message.

Unlike the REST API, there is no need to check an additional status inside the response body. Failed calls end with a gRPC status other than OK, without a response message.

The GREEN-API error text is passed in the message field of the gRPC status.

Mapping of HTTP codes to gRPC statuses#

GREEN-API HTTP error codes are converted to gRPC statuses as follows:

HTTP code gRPC status
400 and other 4xx InvalidArgument
401 Unauthenticated
403 FailedPrecondition
404 NotFound
429 ResourceExhausted
466 ResourceExhausted, if the code means a limit has been exceeded
500 Internal
501 and above Unavailable
503 / service unavailable Unavailable
deadline expired DeadlineExceeded
call cancelled by the client Canceled

When to retry a request#

A repeated call is recommended for the ResourceExhausted and Unavailable statuses.

For ResourceExhausted, a retry is acceptable if the error is caused by the request rate limit (429) or by an exhausted quota (466). For Unavailable, it is recommended to use retries with an increasing delay (backoff).

The InvalidArgument, Unauthenticated, FailedPrecondition and NotFound errors are, as a rule, not resolved by simply repeating the request. Before calling again, fix the cause of the error. Sending methods have their own rules β€” see Resending messages.

ResourceExhausted can also be returned when the allowed chunk size is exceeded in a streaming upload. In this case a retry with backoff will not help: reduce the chunk size. For details, see Streaming calls in the gRPC API.

Resending messages#

Message sending methods, including SendMessage, SendFileByUrl and SendFileByUpload, do not use an idempotency key. Therefore, the server cannot reliably determine whether a repeated request is a retry or a new send, and each such call is processed as a separate operation.

This is especially important for the Unavailable, DeadlineExceeded and Canceled errors: the message may have been accepted and sent by the server even if the client did not receive a successful response. Automatically retrying such a call may result in the same message being sent again.

Before resending, it is recommended to check whether the message has already been sent. To do this, you can use the LastOutgoingMessages and ShowMessagesQueue methods. If the message is missing both from the recent outgoing messages and from the sending queue, the request can be retried.

Examples:

Generating a gRPC client#

You can get a gRPC client in two ways.

Ready-made packages. Generated packages are published to the Buf Schema Registry (BSR) for the buf.build/greenapi/whatsapp-api module. For Go, you can add them with go get; local client generation is not required:

go get buf.build/gen/go/greenapi/whatsapp-api/protocolbuffers/go@latest
go get buf.build/gen/go/greenapi/whatsapp-api/grpc/go@latest

Local generation. Used if there is no ready-made package for the required language or if you need your own generation configuration. buf is used to check protobuf contracts and generate client code:

buf lint       # check the style and correctness of protobuf contracts
buf generate   # generate client code

The buf generate command generates client code for Go, JavaScript/TypeScript, Java, C++ and C#/.NET according to the buf.gen.yaml configuration. The generated files are placed in the gen/ directory, which is a build artifact and is not included in the repository.

Client and server code#

For Go, both client and server code are generated. The other supported languages require only the client part; however, some generation plugins create client and server types together. For example, for Java, C++ and C#/.NET, a base class for implementing the server may be generated along with the client Stub. To work with the API, the client Stub is sufficient; the server types can be left unused.

gRPC-Web is intended for the client side and does not provide a server implementation. In addition, gRPC-Web does not support client streaming calls, so the UploadFile and SendFileByUpload methods cannot be called through the JavaScript/TypeScript gRPC-Web client. For details, see Streaming calls in the gRPC API.

Installing the plugins#

To generate code, install the plugins for the selected language.

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
curl -L -o protobuf-javascript.tar.gz \
  https://github.com/protocolbuffers/protobuf-javascript/releases/download/v3.21.4/protobuf-javascript-3.21.4-linux-x86_64.tar.gz
mkdir protobuf-javascript && tar -xzf protobuf-javascript.tar.gz -C protobuf-javascript
sudo mv protobuf-javascript/bin/protoc-gen-js /usr/local/bin/
rm -rf protobuf-javascript.tar.gz protobuf-javascript

curl -L -o protoc-gen-grpc-web \
  https://github.com/grpc/grpc-web/releases/download/1.5.0/protoc-gen-grpc-web-1.5.0-linux-x86_64
chmod +x protoc-gen-grpc-web
sudo mv protoc-gen-grpc-web /usr/local/bin/
GRPC_JAVA_VERSION=1.68.1
curl -L -o protoc-gen-grpc-java \
  "https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/${GRPC_JAVA_VERSION}/protoc-gen-grpc-java-${GRPC_JAVA_VERSION}-linux-x86_64.exe"
chmod +x protoc-gen-grpc-java
sudo mv protoc-gen-grpc-java /usr/local/bin/
sudo apt install protobuf-compiler-grpc   # Debian/Ubuntu
brew install grpc                         # macOS
GRPC_TOOLS_VERSION=2.66.0
curl -L -o grpc.tools.nupkg \
  "https://www.nuget.org/api/v2/package/Grpc.Tools/${GRPC_TOOLS_VERSION}"
mkdir grpc-tools-extract
unzip -q grpc.tools.nupkg -d grpc-tools-extract
sudo cp grpc-tools-extract/tools/linux_x64/grpc_csharp_plugin /usr/local/bin/
sudo chmod +x /usr/local/bin/grpc_csharp_plugin
rm -rf grpc.tools.nupkg grpc-tools-extract

For protoc-gen-js on Linux, at least in version 3.21.4, the paths to the generated files may contain the ./ prefix. In this case, buf outputs the following warning:

does not conform to the Protobuf generation specification

The warning is output for each such file and does not prevent generation: protoc accepts such paths.

For the C# plugin, the base_namespace parameter set in buf.gen.yaml is additionally used. It distributes the generated files across directories according to their namespaces and prevents conflicts between files with the same name from different packages.

Python#

Python is not included in the current buf generate configuration. To generate Python code, use the grpcio-tools package, which is run directly with python3 -m grpc_tools.protoc:

python3 -m venv .venv
.venv/bin/pip install grpcio-tools
.venv/bin/python3 -m grpc_tools.protoc -I proto \
  --python_out=gen/python --grpc_python_out=gen/python \
  $(find proto -name "*.proto")

Generation produces Python modules for protobuf messages and gRPC services. The _grpc.py file contains the client Stub and the Servicer server class.

To work with GREEN-API, only the client Stub is required; the Servicer server class can be left unused.

Version compatibility#

Each domain is versioned independently: the v1 version refers to a specific package, not to the whole contract. Therefore, a change to one domain does not require changing the versions of the other domains.

To check whether a change breaks backward compatibility with already generated client code, use the buf breaking command:

buf breaking --against '.git#branch=master'
buf breaking --against '.git#tag=v1.2.0'

The command compares the current version of the protobuf contracts with the specified Git branch or tag and detects incompatible changes, such as removed fields, changed field types, renamed RPC methods and other changes that break backward compatibility.

Documentation for the service methods#